@resin/pinejs
Version:
Pine.js is a sophisticated rules-driven API engine that enables you to define rules in a structured subset of English. Those rules are used in order for Pine.js to generate a database schema and the associated [OData](http://www.odata.org/) API. This make
111 lines (100 loc) • 4.49 kB
text/coffeescript
_ = require 'lodash'
sbvrTypes = require '@resin/sbvr-types'
getResourceName = (resourceName) ->
idParts = resourceName.split('-')
(
for idPart in idParts
idPart.split(/[ -]/).join('_')
).join('__')
forEachUniqueTable = (model, callback) ->
usedTableNames = {}
for key, table of model when !_.isString(model[key]) and !table.primitive and !usedTableNames[table.name]
usedTableNames[table.name] = true
callback(key, table)
module.exports = (vocabulary, sqlModel) ->
complexTypes = {}
resolveDataType = (fieldType) ->
if sbvrTypes[fieldType]?
if sbvrTypes[fieldType].types.odata.complexType?
complexTypes[fieldType] = sbvrTypes[fieldType].types.odata.complexType
sbvrTypes[fieldType].types.odata.name
else
console.error('Could not resolve type', fieldType)
throw new Error('Could not resolve type' + fieldType)
model = sqlModel.tables
associations = []
forEachUniqueTable model, (key, { name: resourceName, fields }) ->
resourceName = getResourceName(resourceName)
for { dataType, required, references } in fields when dataType == 'ForeignKey'
{ resourceName: referencedResource } = references
associations.push(
name: resourceName + referencedResource
ends: [
{ resourceName, cardinality: if required then '1' else '0..1' }
{ resourceName: referencedResource, cardinality: '*' }
]
)
return """
<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
<edmx:DataServices xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:DataServiceVersion="2.0">
<Schema Namespace="#{vocabulary}"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
""" +
forEachUniqueTable(model, (key, { idField, name: resourceName, fields }) ->
resourceName = getResourceName(resourceName)
"""
<EntityType Name="#{resourceName}">
<Key>
<PropertyRef Name="#{idField}" />
</Key>
""" + (
for { dataType, fieldName, required } in fields when dataType != 'ForeignKey'
dataType = resolveDataType(dataType)
fieldName = getResourceName(fieldName)
"""<Property Name="#{fieldName}" Type="#{dataType}" Nullable="#{not required}" />"""
).join('\n') + '\n' + (
for { dataType, fieldName, references } in fields when dataType == 'ForeignKey'
{ tableName: referencedResource } = references
fieldName = getResourceName(fieldName)
"""<NavigationProperty Name="#{fieldName}" Relationship="#{vocabulary}.#{resourceName + referencedResource}" FromRole="#{resourceName}" ToRole="#{referencedResource}" />"""
).join('\n') + '\n' + '''
</EntityType>'''
).join('\n\n') + (
for { name, ends } in associations
name = getResourceName(name)
"""<Association Name="#{name}">""" + '\n\t' + (
for { resourceName, cardinality } in ends
"""<End Role="#{resourceName}" Type="#{vocabulary}.#{resourceName}" Multiplicity="#{cardinality}" />"""
).join('\n\t') + '\n' +
'''</Association>'''
).join('\n') + """
<EntityContainer Name="#{vocabulary}Service" m:IsDefaultEntityContainer="true">
""" +
forEachUniqueTable(model, (key, { name: resourceName }) ->
resourceName = getResourceName(resourceName)
"""<EntitySet Name="#{resourceName}" EntityType="#{vocabulary}.#{resourceName}" />"""
).join('\n') + '\n' + (
for { name, ends } in associations
name = getResourceName(name)
"""<AssociationSet Name="#{name}" Association="#{vocabulary}.#{name}">""" + '\n\t' + (
for { resourceName, cardinality } in ends
"""<End Role="#{resourceName}" EntitySet="#{vocabulary}.#{resourceName}" />"""
).join('\n\t') + '''
</AssociationSet>'''
).join('\n') +
# <FunctionImport Name="GetProductsByRating" EntitySet="Products" ReturnType="Collection(ODataDemo.Product)" m:HttpMethod="GET">
# <Parameter Name="rating" Type="Edm.Int32" Mode="In" />
# </FunctionImport>
'''
</EntityContainer>''' +
(
for typeName, complexType of complexTypes
complexType
).join('\n') + '''
</Schema>
</edmx:DataServices>
</edmx:Edmx>'''
module.exports.version = require('../../package.json').version