UNPKG

11.9 kBMarkdownView Raw
1# Cradle - A Schema Pipeline [![Build Status](https://gatewayapps.visualstudio.com/Cradle/_apis/build/status/Cradle%20CI)](https://gatewayapps.visualstudio.com/Cradle/_build/latest?definitionId=34)
2## What is Cradle?
3Cradle is a tool for loading data models from one place and emitting it to another. This can be leveraged to eliminate the manual creation of redundant and tedious code within your project/application. We provide the ability to create specs that can, in turn, be executed against emitters with the output resulting in the code you wish to use.
4
5[Getting Started](#getting-started)
6[An Example Cradle Spec](#an-example-cradle-spec)
7[Cradle Schema](#cradle-schema)
8[The Cradle CLI](#the-cradle-cli)
9[Configuration](#configuration)
10[Loaders](#loaders)
11[Emitters](#emitters)
12
13
14## Getting Started
15To get started, first install Cradle in your local project folder:
16`npm i --save-dev @gatewayapps/cradle`
17
18## The Cradle Flow
19Cradle was built to load a schema from any source via CradleLoaders and emit to any destination via CradleEmitters.
20
21When you execute ```npx cradle emit```, it will load your schema, then send it to each of your configured emitters. We have developed a few emitters for you to use (@gatewayapps/cradle-template-emitter and @gatewayapps/cradle-react-emitter), but the API is simple to understand and implement.
22
23## Cradle Loader API
24If you want to develop a custom Cradle Loader, (for instance, loading from Postgres or Mongo), all you have to do is implement ICradleLoader in a npm module.
25```
26 prepareLoader: (options: {[key: string]: any}, console: IConsole) => Promise < void >
27 readModelNames: () => Promise < string[] >
28 readModelPropertyNames: (modelName: string) => Promise < string[] >
29 readModelPropertyType: (modelName: string, propertyName: string) => Promise < PropertyType >
30 readModelReferenceNames: (modelName: string) => Promise < string[] >
31 readModelReferenceType: (modelName: string, referenceName: string) => Promise < ModelReference >
32 readModelMetadata: (modelName: string) => Promise < object >
33 finalizeSchema: (schema: CradleSchema) => Promise < CradleSchema >
34 loadSchema: () => Promise<CradleSchema>
35```
36
37You can reference @gatewayapps/cradle-sql-loader for a functioning loader
38
39## Cradle Emitter API
40
41You can also write a custom emitter. Suppose you wanted to write your schema to a database, you could implement a sql-emitter by implementing the ICradleEmitter interface.
42```
43 prepareEmitter(options: IEmitterOptions, console: IConsole)
44 emitSchema(schema: CradleSchema)
45```
46
47You can reference @gatewayapps/cradle-template-emitter or @gatewayapps/cradle-react-emitter to see a functioning emitter.
48
49## An Example Cradle Spec
50Cradle provides a custom loader and emitter out of the box called spec. The cradle spec is something we developed for easily modeling our data in an agnostic way. Here's a sample
51```
52Film:
53 properties:
54 id: integer primary auto(1,1)
55 name: string(100)
56 totalBoxOffice: decimal min(0)
57 releaseDate: datetime
58 isDeleted: boolean default(false) delete
59 actors:
60 isArray: true
61 modelRef: Actor
62 operations:
63 createFilm:
64 returns: Film
65 arguments:
66 name:
67
68Actor:
69 properties:
70 id: integer primary auto(1,1)
71 firstName: string(100)
72 lastName: string(100)
73 dateOfBirth: datetime
74```
75To learn more about defining a cradle spec, see the wiki page [here](https://github.com/gatewayapps/cradle/wiki/The-Cradle-Spec)
76
77## Cradle Schema
78Let's see what a cradle schema looks like as a JSON object:
79```
80{
81 "Models": [
82 {
83 "Name": "Film",
84 "Properties": {
85 "id": {
86 "TypeName": "Integer",
87 "IsPrimaryKey": true,
88 "AllowNull": false,
89 "Unique": false,
90 "Autogenerate": {
91 "Seed": 1,
92 "Increment": 1
93 }
94 },
95 "name": {
96 "TypeName": "String",
97 "IsPrimaryKey": false,
98 "AllowNull": false,
99 "Unique": false,
100 "MaximumLength": 100
101 },
102 "totalBoxOffice": {
103 "TypeName": "Decimal",
104 "IsPrimaryKey": false,
105 "AllowNull": false,
106 "Unique": false,
107 "MinimumValue": 0,
108 "Precision": 18,
109 "Scale": 2
110 },
111 "releaseDate": {
112 "TypeName": "DateTime",
113 "IsPrimaryKey": false,
114 "AllowNull": false,
115 "Unique": false
116 },
117 "isDeleted": {
118 "TypeName": "Boolean",
119 "IsPrimaryKey": false,
120 "AllowNull": false,
121 "DefaultValue": false,
122 "Unique": false
123 },
124 "actors": {
125 "TypeName": "Array",
126 "IsPrimaryKey": false,
127 "AllowNull": false,
128 "DefaultValue": [],
129 "Unique": false,
130 "MemberType": {
131 "TypeName": "ModelReference",
132 "IsPrimaryKey": false,
133 "AllowNull": true,
134 "DefaultValue": null,
135 "Unique": false,
136 "ModelName": "Actor",
137 "ModelType": {
138 "TypeName": "Object",
139 "IsPrimaryKey": false,
140 "AllowNull": false,
141 "Unique": false,
142 "Members": {
143 "id": {
144 "TypeName": "Integer",
145 "IsPrimaryKey": true,
146 "AllowNull": false,
147 "Unique": false,
148 "Autogenerate": {
149 "Seed": 1,
150 "Increment": 1
151 }
152 },
153 "firstName": {
154 "TypeName": "String",
155 "IsPrimaryKey": false,
156 "AllowNull": false,
157 "Unique": false,
158 "MaximumLength": 100
159 },
160 "lastName": {
161 "TypeName": "String",
162 "IsPrimaryKey": false,
163 "AllowNull": false,
164 "Unique": false,
165 "MaximumLength": 100
166 },
167 "dateOfBirth": {
168 "TypeName": "DateTime",
169 "IsPrimaryKey": false,
170 "AllowNull": false,
171 "Unique": false
172 }
173 }
174 }
175 }
176 }
177 },
178 "References": {}
179 },
180 {
181 "Name": "Actor",
182 "Properties": {
183 "id": {
184 "TypeName": "Integer",
185 "IsPrimaryKey": true,
186 "AllowNull": false,
187 "Unique": false,
188 "Autogenerate": {
189 "Seed": 1,
190 "Increment": 1
191 }
192 },
193 "firstName": {
194 "TypeName": "String",
195 "IsPrimaryKey": false,
196 "AllowNull": false,
197 "Unique": false,
198 "MaximumLength": 100
199 },
200 "lastName": {
201 "TypeName": "String",
202 "IsPrimaryKey": false,
203 "AllowNull": false,
204 "Unique": false,
205 "MaximumLength": 100
206 },
207 "dateOfBirth": {
208 "TypeName": "DateTime",
209 "IsPrimaryKey": false,
210 "AllowNull": false,
211 "Unique": false
212 }
213 },
214 "References": {}
215 }
216 ]
217}
218```
219- `Models`: is an array of the models defined in the cradle spec file(s)
220- `TypeName`: is the cradle data type
221- `AllowNull`: is true if the `?` notation was used to define the property
222- `Unique`: is true if the `unique` keyword was used to define the property
223- If the property is an array, then there is a `MemberType` property which contains the values and data type of the array
224
225## The Cradle CLI
226Cradle provides a CLI with a few different commands:
227
228### verify
229Use the `verify` command to ensure that any given spec file is valid:
230`npx cradle verify -c [path to cradle config]`
231
232This command will output the cradle spec in the terminal or command window in which the command was executed. Any warnings or errors will also be output.
233
234### emit
235Use the `emit` command to run the specified emitter:
236`npx cradle emit -c [path to cradle config] -e spec`
237
238This command will run the specified emitters(see the Configuration section). Use the `-e` argument to specify a particular emitter or omit it to run all configured emitters.
239
240## Configuration
241Cradle uses a JavaScript based configuration file in order to execute loading the spec and executing emitters. Below is an example configuration file:
242
243```
244const cradle = require('@gatewayapps/cradle')
245const path = require('path')
246
247const loaderOptions = new cradle.LoaderOptions('spec', {
248 source: './examples/specs/cradle-base.yaml'
249}, console)
250
251const emitterOpts = [
252 new cradle.EmitterOptions('schemaTest', '@gatewayapps/cradle-template-emitter', {
253 sourcePath: './examples/templates/schemaTest.handlebars',
254 outputPath: './examples/server/test/schemaTest.ts',
255 overwriteExisting: true,
256 mode: 'schema',
257 shouldEmit: (model) => {
258 return model.Meta !== undefined && model.Meta.topLevel
259 }
260 }, console),
261 new cradle.EmitterOptions('serverModels', '@gatewayapps/cradle-template-emitter', {
262 sourcePath: './examples/templates/serverModel.handlebars',
263 outputPath: './examples/server/models/{{Name}}.ts',
264 overwriteExisting: true,
265 languageType: 'mongoose',
266 shouldEmit: (model) => {
267 return model.Meta !== undefined && model.Meta.topLevel
268 }
269 }, console)
270]
271
272module.exports = new cradle.CradleConfig(loaderOptions, emitterOpts)
273
274```
275
276Let's break down the configuration file in more detail:
277```
278const loaderOptions = new cradle.LoaderOptions('spec', {
279 source: './examples/specs/cradle-base.yaml'
280}, console)
281```
282This section configures the cradle spec loader. This is required in order to read the cradle spec files. The first option is the type of loader(`spec`), the second option is the location of the cradle spec file.
283
284```
285const emitterOpts = [
286 new cradle.EmitterOptions('schemaTest', '@gatewayapps/cradle-template-emitter', {
287 sourcePath: './examples/templates/schemaTest.handlebars',
288 outputPath: './examples/server/test/schemaTest.ts',
289 overwriteExisting: true,
290 mode: 'schema',
291 shouldEmit: (model) => {
292 return model.Meta !== undefined && model.Meta.topLevel
293 }
294 }, console),
295 new cradle.EmitterOptions('serverModels', '@gatewayapps/cradle-template-emitter', {
296 sourcePath: './examples/templates/serverModel.handlebars',
297 outputPath: './examples/server/models/{{Name}}.ts',
298 overwriteExisting: true,
299 languageType: 'mongoose',
300 shouldEmit: (model) => {
301 return model.Meta !== undefined && model.Meta.topLevel
302 }
303 }, console)
304]
305```
306This section is configuring emitters. These two examples uses the [cradle template emitter](https://github.com/gatewayapps/cradle-template-emitter) in order to generate code. More information about these arguments can be found in the ReadMe for that particular library.
307
308## Loaders
309- Cradle Spec Loader: This is included in cradle and drives the loading of the cradle spec files
310- [MSSQL Loader](cradle-mssql-loader): This loader can be used to read the database schema from a MSSQL database and generate a cradle spec
311
312## Emitters
313- Cradle Spec Emitter: This is included in cradle and can be used to output a generated spec file
314- [Cradle Template Emitter](https://github.com/gatewayapps/cradle-template-emitter): This emitter leverages Handlebars templating in order to generate pretty much any code desired
315- [Cradle React Emitter](https://github.com/gatewayapps/cradle-react-emitter): This emitter generates basic React components for model properties. Rather than starting a UI from scratch, this emitter provides a starting point with functional components that can then be tweaked/altered.
316
\No newline at end of file