├── .babelrc ├── .gitignore ├── .vscode └── tasks.json ├── README.md ├── jsconfig.json ├── package-lock.json ├── package.json ├── src ├── edm.ts └── metacode.ts ├── tests ├── schema.json ├── schema2.json └── tses5-tests.js └── tsconfig.json /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"], 3 | "plugins": ["transform-decorators-legacy","transform-class-properties", "add-module-exports"] 4 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "tsc", 4 | "showOutput": "always", 5 | "isShellCommand": true, 6 | "args": [], 7 | "problemMatcher": "$tsc" 8 | } 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #OData V4 metadata classes 2 | 3 | This library implements the EDM and EMDX classes from the OData CSDL V4. 4 | 5 | 6 | ## Features 7 | - Edm and Edmx classes 8 | - will provide Validation logic - based on specs (-on the way) 9 | - will Download and parse metadata from $metadata document or uri endpoint 10 | 11 | ##Usage 12 | 13 | ``` 14 | $ npm install odata-v4-metadata 15 | ``` 16 | 17 | then just 18 | 19 | ```javascript 20 | import {Edm} from 'odata-v4-metadata' 21 | 22 | let entityType = new edm.EntityType({ name: "Orders", property: [{ name:"OrderID", type:edm.Integer}] 23 | entityType.properties.push(new Edm.Property(...)) 24 | ``` 25 | 26 | ## Edm classes implemented 27 | 28 | ### Edm.Action 29 | 30 | ### Edm.ComplexType 31 | 32 | ### Edm.EntityType 33 | 34 | ### Edm.EnumType 35 | 36 | ### Edm.Function 37 | 38 | ### Edm.Member 39 | 40 | ### Edm.NavigationProperty 41 | 42 | ### Edm.Parameter 43 | 44 | ### Edm.Property 45 | 46 | ### Edm.PropertyRef 47 | 48 | ### Edm.ReferentialConstraint 49 | 50 | ### Edm.ReturnType 51 | 52 | ### Edm.Schema 53 | 54 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "module": "commonjs", 5 | "diagnostics": true, 6 | "experimentalDecorators": true 7 | }, 8 | "xfiles": [ 9 | "typings/**/*.d.ts","src/**.js","lib/**.js" 10 | ] 11 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "odata-v4-metadata", 3 | "version": "0.1.4", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "assertion-error": { 8 | "version": "1.0.2", 9 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", 10 | "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", 11 | "dev": true 12 | }, 13 | "balanced-match": { 14 | "version": "1.0.0", 15 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 16 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 17 | "dev": true 18 | }, 19 | "brace-expansion": { 20 | "version": "1.1.8", 21 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", 22 | "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", 23 | "dev": true, 24 | "requires": { 25 | "balanced-match": "1.0.0", 26 | "concat-map": "0.0.1" 27 | } 28 | }, 29 | "browser-stdout": { 30 | "version": "1.3.0", 31 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", 32 | "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", 33 | "dev": true 34 | }, 35 | "chai": { 36 | "version": "3.5.0", 37 | "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", 38 | "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", 39 | "dev": true, 40 | "requires": { 41 | "assertion-error": "1.0.2", 42 | "deep-eql": "0.1.3", 43 | "type-detect": "1.0.0" 44 | } 45 | }, 46 | "charenc": { 47 | "version": "0.0.2", 48 | "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", 49 | "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", 50 | "dev": true 51 | }, 52 | "commander": { 53 | "version": "2.9.0", 54 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", 55 | "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", 56 | "dev": true, 57 | "requires": { 58 | "graceful-readlink": "1.0.1" 59 | } 60 | }, 61 | "concat-map": { 62 | "version": "0.0.1", 63 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 64 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 65 | "dev": true 66 | }, 67 | "crypt": { 68 | "version": "0.0.2", 69 | "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", 70 | "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", 71 | "dev": true 72 | }, 73 | "debug": { 74 | "version": "2.6.8", 75 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", 76 | "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", 77 | "dev": true, 78 | "requires": { 79 | "ms": "2.0.0" 80 | } 81 | }, 82 | "deep-eql": { 83 | "version": "0.1.3", 84 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", 85 | "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", 86 | "dev": true, 87 | "requires": { 88 | "type-detect": "0.1.1" 89 | }, 90 | "dependencies": { 91 | "type-detect": { 92 | "version": "0.1.1", 93 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", 94 | "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", 95 | "dev": true 96 | } 97 | } 98 | }, 99 | "diff": { 100 | "version": "3.2.0", 101 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", 102 | "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", 103 | "dev": true 104 | }, 105 | "escape-string-regexp": { 106 | "version": "1.0.5", 107 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 108 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 109 | "dev": true 110 | }, 111 | "fs.realpath": { 112 | "version": "1.0.0", 113 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 114 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 115 | "dev": true 116 | }, 117 | "glob": { 118 | "version": "7.1.2", 119 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", 120 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", 121 | "dev": true, 122 | "requires": { 123 | "fs.realpath": "1.0.0", 124 | "inflight": "1.0.6", 125 | "inherits": "2.0.3", 126 | "minimatch": "3.0.4", 127 | "once": "1.4.0", 128 | "path-is-absolute": "1.0.1" 129 | } 130 | }, 131 | "graceful-readlink": { 132 | "version": "1.0.1", 133 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", 134 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", 135 | "dev": true 136 | }, 137 | "growl": { 138 | "version": "1.9.2", 139 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", 140 | "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", 141 | "dev": true 142 | }, 143 | "has-flag": { 144 | "version": "1.0.0", 145 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", 146 | "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", 147 | "dev": true 148 | }, 149 | "inflight": { 150 | "version": "1.0.6", 151 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 152 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 153 | "dev": true, 154 | "requires": { 155 | "once": "1.4.0", 156 | "wrappy": "1.0.2" 157 | } 158 | }, 159 | "inherits": { 160 | "version": "2.0.3", 161 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 162 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 163 | "dev": true 164 | }, 165 | "is-buffer": { 166 | "version": "1.1.5", 167 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", 168 | "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", 169 | "dev": true 170 | }, 171 | "json3": { 172 | "version": "3.3.2", 173 | "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", 174 | "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", 175 | "dev": true 176 | }, 177 | "lodash._baseassign": { 178 | "version": "3.2.0", 179 | "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", 180 | "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", 181 | "dev": true, 182 | "requires": { 183 | "lodash._basecopy": "3.0.1", 184 | "lodash.keys": "3.1.2" 185 | } 186 | }, 187 | "lodash._basecopy": { 188 | "version": "3.0.1", 189 | "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", 190 | "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", 191 | "dev": true 192 | }, 193 | "lodash._basecreate": { 194 | "version": "3.0.3", 195 | "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", 196 | "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", 197 | "dev": true 198 | }, 199 | "lodash._getnative": { 200 | "version": "3.9.1", 201 | "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", 202 | "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", 203 | "dev": true 204 | }, 205 | "lodash._isiterateecall": { 206 | "version": "3.0.9", 207 | "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", 208 | "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", 209 | "dev": true 210 | }, 211 | "lodash.create": { 212 | "version": "3.1.1", 213 | "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", 214 | "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", 215 | "dev": true, 216 | "requires": { 217 | "lodash._baseassign": "3.2.0", 218 | "lodash._basecreate": "3.0.3", 219 | "lodash._isiterateecall": "3.0.9" 220 | } 221 | }, 222 | "lodash.isarguments": { 223 | "version": "3.1.0", 224 | "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", 225 | "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", 226 | "dev": true 227 | }, 228 | "lodash.isarray": { 229 | "version": "3.0.4", 230 | "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", 231 | "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", 232 | "dev": true 233 | }, 234 | "lodash.keys": { 235 | "version": "3.1.2", 236 | "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", 237 | "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", 238 | "dev": true, 239 | "requires": { 240 | "lodash._getnative": "3.9.1", 241 | "lodash.isarguments": "3.1.0", 242 | "lodash.isarray": "3.0.4" 243 | } 244 | }, 245 | "md5": { 246 | "version": "2.2.1", 247 | "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", 248 | "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", 249 | "dev": true, 250 | "requires": { 251 | "charenc": "0.0.2", 252 | "crypt": "0.0.2", 253 | "is-buffer": "1.1.5" 254 | } 255 | }, 256 | "minimatch": { 257 | "version": "3.0.4", 258 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 259 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 260 | "dev": true, 261 | "requires": { 262 | "brace-expansion": "1.1.8" 263 | } 264 | }, 265 | "minimist": { 266 | "version": "0.0.8", 267 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 268 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 269 | "dev": true 270 | }, 271 | "mkdirp": { 272 | "version": "0.5.1", 273 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 274 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 275 | "dev": true, 276 | "requires": { 277 | "minimist": "0.0.8" 278 | } 279 | }, 280 | "mocha": { 281 | "version": "3.5.0", 282 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.0.tgz", 283 | "integrity": "sha512-pIU2PJjrPYvYRqVpjXzj76qltO9uBYI7woYAMoxbSefsa+vqAfptjoeevd6bUgwD0mPIO+hv9f7ltvsNreL2PA==", 284 | "dev": true, 285 | "requires": { 286 | "browser-stdout": "1.3.0", 287 | "commander": "2.9.0", 288 | "debug": "2.6.8", 289 | "diff": "3.2.0", 290 | "escape-string-regexp": "1.0.5", 291 | "glob": "7.1.1", 292 | "growl": "1.9.2", 293 | "json3": "3.3.2", 294 | "lodash.create": "3.1.1", 295 | "mkdirp": "0.5.1", 296 | "supports-color": "3.1.2" 297 | }, 298 | "dependencies": { 299 | "glob": { 300 | "version": "7.1.1", 301 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", 302 | "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", 303 | "dev": true, 304 | "requires": { 305 | "fs.realpath": "1.0.0", 306 | "inflight": "1.0.6", 307 | "inherits": "2.0.3", 308 | "minimatch": "3.0.4", 309 | "once": "1.4.0", 310 | "path-is-absolute": "1.0.1" 311 | } 312 | } 313 | } 314 | }, 315 | "mocha-junit-reporter": { 316 | "version": "1.13.0", 317 | "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-1.13.0.tgz", 318 | "integrity": "sha1-Aw24xTCyRGZyU7A4YdTNM29+Vsg=", 319 | "dev": true, 320 | "requires": { 321 | "debug": "2.6.8", 322 | "md5": "2.2.1", 323 | "mkdirp": "0.5.1", 324 | "xml": "1.0.1" 325 | } 326 | }, 327 | "ms": { 328 | "version": "2.0.0", 329 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 330 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 331 | "dev": true 332 | }, 333 | "once": { 334 | "version": "1.4.0", 335 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 336 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 337 | "dev": true, 338 | "requires": { 339 | "wrappy": "1.0.2" 340 | } 341 | }, 342 | "path-is-absolute": { 343 | "version": "1.0.1", 344 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 345 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 346 | "dev": true 347 | }, 348 | "rimraf": { 349 | "version": "2.6.1", 350 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", 351 | "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", 352 | "dev": true, 353 | "requires": { 354 | "glob": "7.1.2" 355 | } 356 | }, 357 | "supports-color": { 358 | "version": "3.1.2", 359 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", 360 | "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", 361 | "dev": true, 362 | "requires": { 363 | "has-flag": "1.0.0" 364 | } 365 | }, 366 | "type-detect": { 367 | "version": "1.0.0", 368 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", 369 | "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", 370 | "dev": true 371 | }, 372 | "typescript": { 373 | "version": "2.4.2", 374 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.4.2.tgz", 375 | "integrity": "sha1-+DlfhdRZJ2BnyYiqQYN6j4KHCEQ=", 376 | "dev": true 377 | }, 378 | "wrappy": { 379 | "version": "1.0.2", 380 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 381 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 382 | "dev": true 383 | }, 384 | "xml": { 385 | "version": "1.0.1", 386 | "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", 387 | "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", 388 | "dev": true 389 | } 390 | } 391 | } 392 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "odata-v4-metadata", 3 | "version": "0.1.4", 4 | "description": "OData metadata utilities", 5 | "main": "lib/edm.js", 6 | "homepage": "https://github.com/jaystack/odata-v4-metadata.git", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/jaystack/odata-v4-metadata.git" 10 | }, 11 | "typings": "lib/edm.d.ts", 12 | "author": "", 13 | "license": "ISC", 14 | "engines": { 15 | "node": ">=0.6.0" 16 | }, 17 | "devDependencies": { 18 | "mocha": "^3.2.0", 19 | "mocha-junit-reporter": "^1.13.0", 20 | "chai": "^3.5.0", 21 | "rimraf": "^2.6.1", 22 | "typescript": "^2.4.0" 23 | }, 24 | "scripts": { 25 | "prebuild": "rimraf lib", 26 | "build": "tsc", 27 | "test": "mocha tests", 28 | "prepublish": "npm run build" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/edm.ts: -------------------------------------------------------------------------------- 1 | import * as metacode from './metacode' 2 | 3 | export namespace Edm { 4 | export class PrimitiveType { 5 | constructor(public className: string) { } 6 | toString() { return this.className } 7 | } 8 | 9 | 10 | export const Binary = new PrimitiveType('Edm.Binary') 11 | export const Boolean = new PrimitiveType('Edm.Boolean') 12 | export const Byte = new PrimitiveType('Edm.Byte') 13 | export const Date = new PrimitiveType('Edm.Date') 14 | export const DateTimeOffset = new PrimitiveType('Edm.DateTimeOffset') 15 | export const Decimal = new PrimitiveType('Edm.Decimal') 16 | export const Double = new PrimitiveType('Edm.Double') 17 | export const Duration = new PrimitiveType('Edm.Duration') 18 | export const Guid = new PrimitiveType('Edm.Guid') 19 | export const Int16 = new PrimitiveType('Edm.Int16') 20 | export const Int32 = new PrimitiveType('Edm.Int32') 21 | export const Int64 = new PrimitiveType('Edm.Int64') 22 | export const SByte = new PrimitiveType('Edm.SByte') 23 | export const Single = new PrimitiveType('Edm.Single') 24 | export const Stream = new PrimitiveType('Edm.Stream') 25 | export const String = new PrimitiveType('Edm.String') 26 | export const TimeOfDay = new PrimitiveType('Edm.TimeOfDay') 27 | export const Geography = new PrimitiveType('Edm.Geography') 28 | export const GeographyPoint = new PrimitiveType('Edm.GeographyPoint') 29 | export const GeographyLineString = new PrimitiveType('Edm.GeographyLineString') 30 | export const GeographyPolygon = new PrimitiveType('Edm.GeographyPolygon') 31 | export const GeographyMultiPoint = new PrimitiveType('Edm.GeographyMultiPoint') 32 | export const GeographyMultiLineString = new PrimitiveType('Edm.GeographyMultiLineString') 33 | export const GeographyMultiPolygon = new PrimitiveType('Edm.GeographyMultiPolygon') 34 | export const GeographyCollection = new PrimitiveType('Edm.GeographyCollection') 35 | export const Geometry = new PrimitiveType('Edm.Geometry') 36 | export const GeometryPoint = new PrimitiveType('Edm.GeometryPoint') 37 | export const GeometryLineString = new PrimitiveType('Edm.GeometryLineString') 38 | export const GeometryPolygon = new PrimitiveType('Edm.GeometryPolygon') 39 | export const GeometryMultiPoint = new PrimitiveType('Edm.GeometryMultiPoint') 40 | export const GeometryMultiLineString = new PrimitiveType('Edm.GeometryMultiLineString') 41 | export const GeometryMultiPolygon = new PrimitiveType('Edm.GeometryMultiPolygon') 42 | export const GeometryCollection = new PrimitiveType('Edm.GeometryCollection') 43 | 44 | 45 | let MemberAttribute = metacode.MemberAttribute 46 | let parse = metacode.parse 47 | let required = metacode.required 48 | let defaultValue = metacode.defaultValue 49 | let parseAs = metacode.parseAs 50 | let AttributeFunctionChain = metacode.AttributeFunctionChain 51 | let mapArray = (sourceField, factory) => new metacode.AttributeFunctionChain( 52 | (d, i) =>d[sourceField], 53 | (props, i) => Array.isArray(props) ? props : (props ? [props] : []), 54 | (props, i) => props.map(prop => factory(prop, i))) 55 | 56 | let primitiveAnnotationValue = (sourceField) => new metacode.AttributeFunctionChain( 57 | (d, i) => { 58 | if(d['collection'] && d['collection'][0] && Array.isArray(d['collection'][0][sourceField]) && !d[sourceField]){ 59 | return d['collection'][0][sourceField].map(x => x.text) 60 | } 61 | var props = d[sourceField]; 62 | if(Array.isArray(props)) { 63 | return props.filter(x => 'text' in x).map(x => x.text)[0] 64 | } else { 65 | return props 66 | } 67 | }) 68 | 69 | 70 | let annotationTypeSelector = (source) => { 71 | for(var i in AnnotationTypes){ 72 | if(i in source || (source['collection'] && source['collection'][0] && i in source['collection'][0])){ 73 | return AnnotationTypes[i] 74 | } 75 | } 76 | return Annotation 77 | } 78 | 79 | 80 | export class EdmItemBase { 81 | 82 | constructor(definition?: any, public parent?:EdmItemBase) { 83 | definition && this.loadFrom(definition) 84 | } 85 | 86 | loadFrom(definition) { 87 | 88 | var proto = Object.getPrototypeOf(this) 89 | MemberAttribute.getMembers(proto).forEach( membername => { 90 | var parser = MemberAttribute.getAttributeValue(proto, membername, "serialize") 91 | if (parser) { 92 | var v = parser.invoke(definition, this) 93 | this[membername] = v 94 | } 95 | }) 96 | } 97 | 98 | } 99 | 100 | 101 | 102 | export class Property extends EdmItemBase { 103 | @parse 104 | @required 105 | public name: string 106 | 107 | 108 | @parse 109 | @required 110 | public type: string; 111 | 112 | @parse 113 | @defaultValue(true) 114 | public nullable: boolean; 115 | 116 | @parse 117 | public maxLength: number; 118 | 119 | @parse 120 | public precision: number; 121 | 122 | @parse 123 | public scale: number; 124 | 125 | @parse 126 | public unicode: boolean; 127 | 128 | @parse 129 | @defaultValue(0) 130 | public SRID: number; 131 | 132 | @parse 133 | public defaultValue: any; 134 | 135 | @parse 136 | public concurrencyMode: String 137 | 138 | @parseAs(mapArray("annotation", (prop, i) => new (annotationTypeSelector(prop))(prop, i))) 139 | public annotations: Array 140 | } 141 | 142 | export class NavigationProperty extends EdmItemBase { 143 | @parse 144 | @required 145 | public name: string; 146 | 147 | 148 | @parse 149 | @required 150 | public type: string; 151 | 152 | @parse 153 | @defaultValue(true) 154 | public nullable: boolean; 155 | 156 | @parse 157 | public partner: string 158 | 159 | @parse 160 | public containsTarget: boolean 161 | 162 | @parseAs(mapArray("referentialConstraint", (prop, i) => new ReferentialConstraint(prop, i))) 163 | public referentialConstraints: Array 164 | 165 | //TODO onDelete 166 | 167 | 168 | @parseAs(mapArray("annotation", (prop, i) => new (annotationTypeSelector(prop))(prop, i))) 169 | public annotations: Array 170 | } 171 | 172 | export class ReferentialConstraint extends EdmItemBase { 173 | @parse 174 | @required 175 | public property: string 176 | 177 | @parse 178 | @required 179 | public referencedProperty: string 180 | 181 | } 182 | 183 | export class PropertyRef extends EdmItemBase { 184 | @parse 185 | @required 186 | public name: string; 187 | 188 | @parse 189 | //@requiredIfContainerIsComplexType 190 | public alias: string; 191 | } 192 | 193 | export class Key extends EdmItemBase { 194 | 195 | @parseAs(mapArray("propertyRef", (prop, i) => new PropertyRef(prop, i))) 196 | public propertyRefs: Array 197 | //@arrayMinLength(1) 198 | } 199 | 200 | 201 | export class EntityType extends EdmItemBase { 202 | 203 | @parse 204 | @required 205 | public name: string; 206 | 207 | 208 | @parseAs(new AttributeFunctionChain( 209 | (d, i) =>d.key, 210 | (props, i) => props || [], 211 | (props, i) => props.map(prop => new Key(prop, i)), 212 | (props) => props[0])) 213 | public key: Key; 214 | 215 | @parse 216 | public baseType: string; 217 | 218 | @parse 219 | public abstract: boolean; 220 | 221 | @parse 222 | public openType: boolean; 223 | 224 | @parse 225 | public hasStream: boolean; 226 | 227 | 228 | 229 | @parseAs(mapArray("property", (prop, i) => new Property(prop, i))) 230 | public properties: Array; 231 | 232 | @parseAs(mapArray("navigationProperty", (prop, i) => new NavigationProperty(prop, i))) 233 | public navigationProperties: Array; 234 | 235 | @parseAs(mapArray("annotation", (prop, i) => new (annotationTypeSelector(prop))(prop, i))) 236 | public annotations: Array 237 | } 238 | 239 | export class ComplexType extends EdmItemBase { 240 | 241 | @parse 242 | @required 243 | public name: string; 244 | 245 | @parse 246 | public baseType: string; 247 | 248 | @parse 249 | public abstract: boolean; 250 | 251 | @parse 252 | public openType: boolean; 253 | 254 | @parse 255 | public hasStream: boolean; 256 | 257 | @parseAs(mapArray("property", (prop, i) => new Property(prop, i))) 258 | public properties: Array; 259 | 260 | @parseAs(mapArray("navigationProperty", (prop, i) => new NavigationProperty(prop, i))) 261 | public navigationProperties: Array; 262 | 263 | @parseAs(mapArray("annotation", (prop, i) => new (annotationTypeSelector(prop))(prop, i))) 264 | public annotations: Array 265 | } 266 | export class Parameter extends EdmItemBase { 267 | 268 | @parse 269 | @required 270 | public name: string 271 | 272 | 273 | @parse 274 | @required 275 | public type: string; 276 | 277 | @parse 278 | @defaultValue(true) 279 | public nullable: boolean; 280 | 281 | @parse 282 | public maxLength: number; 283 | 284 | @parse 285 | public precision: number; 286 | 287 | @parse 288 | public scale: number; 289 | 290 | @parse 291 | public unicode: boolean; 292 | 293 | @parse 294 | @defaultValue(0) 295 | public SRID: number; 296 | 297 | @parseAs(mapArray("annotation", (prop, i) => new (annotationTypeSelector(prop))(prop, i))) 298 | public annotations: Array 299 | 300 | // according to specs there is no default value for params. but is that right? 301 | // @parse 302 | // public defaultValue: any; 303 | } 304 | export class ReturnType extends EdmItemBase { 305 | @parse 306 | public type: string 307 | 308 | @parse 309 | @defaultValue(true) 310 | public nullable: boolean 311 | 312 | @parseAs(mapArray("annotation", (prop, i) => new (annotationTypeSelector(prop))(prop, i))) 313 | public annotations: Array 314 | } 315 | 316 | export class Invokable extends EdmItemBase { } 317 | 318 | export class Action extends Invokable { 319 | @parse 320 | @required 321 | public name: string 322 | 323 | @parse 324 | public isBound: boolean 325 | 326 | @parse 327 | public entitySetPath: string 328 | 329 | @parseAs(mapArray("parameter", (prop, i) => new Parameter(prop, i))) 330 | public parameters: Array 331 | 332 | @parseAs(new AttributeFunctionChain( 333 | (d, i) => d.returnType, 334 | (rt, i) => new ReturnType(rt, i))) 335 | 336 | public returnType: ReturnType 337 | 338 | @parseAs(mapArray("annotation", (prop, i) => new (annotationTypeSelector(prop))(prop, i))) 339 | public annotations: Array 340 | } 341 | 342 | 343 | export class Function extends Invokable { 344 | @parse 345 | @required 346 | public name: string 347 | 348 | @parse 349 | public isBound: boolean 350 | 351 | @parse 352 | public entitySetPath: string 353 | 354 | @parseAs(mapArray("parameter", (prop, i) => new Parameter(prop, i))) 355 | public parameters: Array 356 | 357 | @parseAs(new AttributeFunctionChain( 358 | (d, i) => d.returnType, 359 | (rt, i) => new ReturnType(rt, i))) 360 | public returnType: ReturnType 361 | 362 | @parse 363 | public isComposable: boolean 364 | 365 | @parseAs(mapArray("annotation", (prop, i) => new (annotationTypeSelector(prop))(prop, i))) 366 | public annotations: Array 367 | } 368 | export class Member extends EdmItemBase { 369 | @parse 370 | @required 371 | public name: string 372 | 373 | @parse 374 | public value: number 375 | 376 | @parseAs(mapArray("annotation", (prop, i) => new (annotationTypeSelector(prop))(prop, i))) 377 | public annotations: Array 378 | } 379 | 380 | export class EnumType extends EdmItemBase { 381 | @parse 382 | @required 383 | public name: string 384 | 385 | @parse 386 | @required 387 | public namespace: string 388 | 389 | @parse 390 | //@oneOf(Edm.Byte, Edm.SByte, Edm.Int16, Edm.Int32, Edm.Int64) 391 | @defaultValue(Edm.Int32) 392 | public underlyingType: PrimitiveType 393 | 394 | @parse 395 | public isFlags: boolean 396 | 397 | @parseAs(mapArray("member", (prop, i) => new Member(prop, i))) 398 | public members: Array 399 | 400 | @parseAs(mapArray("annotation", (prop, i) => new (annotationTypeSelector(prop))(prop, i))) 401 | public annotations: Array 402 | } 403 | 404 | export class EntitySet extends EdmItemBase { 405 | @parse 406 | @required 407 | public name: string 408 | 409 | @parse 410 | @required 411 | public entityType: string 412 | 413 | @parseAs(mapArray("annotation", (prop, i) => new (annotationTypeSelector(prop))(prop, i))) 414 | public annotations: Array 415 | } 416 | 417 | export class ActionImport extends EdmItemBase { 418 | @parse 419 | @required 420 | public name: string 421 | 422 | @parse 423 | @required 424 | public action: string 425 | 426 | @parseAs(mapArray("annotation", (prop, i) => new (annotationTypeSelector(prop))(prop, i))) 427 | public annotations: Array 428 | } 429 | 430 | export class FunctionImport extends EdmItemBase { 431 | @parse 432 | @required 433 | public name: string 434 | 435 | @parse 436 | @required 437 | public function: string 438 | 439 | @parse 440 | @defaultValue(false) 441 | public includeInServiceDocument: boolean 442 | 443 | @parseAs(mapArray("annotation", (prop, i) => new (annotationTypeSelector(prop))(prop, i))) 444 | public annotations: Array 445 | } 446 | 447 | export class EntityContainer extends EdmItemBase { 448 | @parse 449 | public name: string 450 | 451 | @parseAs(mapArray("entitySet", (prop, i) => new EntitySet(prop, i))) 452 | public entitySets: Array 453 | 454 | @parseAs(mapArray("actionImport", (prop, i) => new ActionImport(prop, i))) 455 | public actionImports: Array 456 | 457 | @parseAs(mapArray("functionImport", (prop, i) => new FunctionImport(prop, i))) 458 | public functionImports: Array 459 | } 460 | 461 | // "Name", "UnderlyingType", "MaxLength", "Unicode", "Precision", "Scale", "SRID" 462 | export class TypeDefinition extends EdmItemBase { 463 | @parse 464 | public name: string 465 | 466 | @parse 467 | public underlyingType: PrimitiveType 468 | 469 | @parse 470 | public maxLength: number 471 | 472 | @parse 473 | public unicode: boolean 474 | 475 | @parse 476 | public precision: number 477 | 478 | @parse 479 | public scale: number 480 | 481 | @parse 482 | @defaultValue(0) 483 | public SRID: number; 484 | 485 | @parseAs(mapArray("annotation", (prop, i) => new (annotationTypeSelector(prop))(prop, i))) 486 | public annotations: Array 487 | } 488 | 489 | export class Schema extends EdmItemBase { 490 | @parse 491 | @required 492 | public namespace: string 493 | 494 | @parse 495 | //@noneOf(["Edm", "odata", "System", "Transient") 496 | public alias: string 497 | 498 | @parseAs(mapArray("enumType", (prop, i) => new EnumType(prop, i))) 499 | public enumTypes: Array 500 | 501 | @parseAs(mapArray("typeDefinition", (prop, i) => new TypeDefinition(prop, i))) 502 | public typeDefinitions: Array 503 | 504 | @parseAs(mapArray("complexType", (prop, i) => new ComplexType(prop, i))) 505 | public complexTypes: Array 506 | 507 | 508 | @parseAs(mapArray("entityType", (prop, i) => new EntityType(prop, i))) 509 | public entityTypes: Array 510 | 511 | @parseAs(mapArray("action", (prop, i) => new Action(prop, i))) 512 | public actions: Array 513 | 514 | @parseAs(mapArray("function", (prop, i) => new Edm.Function(prop, i))) 515 | public functions: Array 516 | 517 | @parseAs(mapArray("entityContainer", (prop, i) => new Edm.EntityContainer(prop, i))) 518 | public entityContainer: Array 519 | 520 | @parseAs(mapArray("annotations", (prop, i) => new Edm.Annotations(prop, i))) 521 | public annotations: Array 522 | } 523 | 524 | 525 | export class DataServices extends EdmItemBase { 526 | @parseAs(mapArray("schema", (prop, i) => new Schema(prop, i))) 527 | public schemas: Array 528 | } 529 | 530 | export class Reference extends EdmItemBase { 531 | @parse 532 | public uri: string 533 | 534 | @parseAs(mapArray("include", (prop, i) => new ReferenceInclude(prop, i))) 535 | public includes: Array 536 | } 537 | 538 | export class ReferenceInclude extends EdmItemBase { 539 | @parse 540 | public namespace: string 541 | 542 | @parse 543 | public alias: string 544 | } 545 | 546 | export class Edmx extends EdmItemBase { 547 | public version = "4.0" 548 | 549 | @parseAs(new AttributeFunctionChain( 550 | (edm) => new Edm.DataServices(edm.dataServices) 551 | )) 552 | public dataServices: DataServices 553 | 554 | @parseAs(mapArray("reference", (prop, i) => new Reference(prop, i))) 555 | public references: Array 556 | } 557 | 558 | export class Annotations extends EdmItemBase { 559 | @parse 560 | @required 561 | public target: string 562 | 563 | @parse 564 | public qualifier: string 565 | 566 | @parseAs(mapArray("annotation", (prop, i) => new (annotationTypeSelector(prop))(prop, i))) 567 | public annotations: Array 568 | } 569 | 570 | export class Annotation extends EdmItemBase { 571 | public annotationType: string = "Unknown"; 572 | 573 | @parse 574 | public term: string 575 | 576 | @parse 577 | public qualifier: string 578 | 579 | @parse 580 | public path: string 581 | } 582 | 583 | export class BinaryAnnotation extends Annotation { 584 | public annotationType: string = "Binary"; 585 | 586 | @parseAs(primitiveAnnotationValue("binary")) 587 | public binary: String 588 | } 589 | 590 | export class BoolAnnotation extends Annotation { 591 | public annotationType: string = "Bool"; 592 | 593 | @parseAs(primitiveAnnotationValue("bool")) 594 | public bool: String 595 | } 596 | 597 | export class DateAnnotation extends Annotation { 598 | public annotationType: string = "Date"; 599 | 600 | @parseAs(primitiveAnnotationValue("date")) 601 | public date: String 602 | } 603 | 604 | export class DateTimeOffsetAnnotation extends Annotation { 605 | public annotationType: string = "DateTimeOffset"; 606 | 607 | @parseAs(primitiveAnnotationValue("dateTimeOffset")) 608 | public dateTimeOffset: String 609 | } 610 | 611 | export class DecimalAnnotation extends Annotation { 612 | public annotationType: string = "Decimal"; 613 | 614 | @parseAs(primitiveAnnotationValue("decimal")) 615 | public decimal: String 616 | } 617 | 618 | export class DurationAnnotation extends Annotation { 619 | public annotationType: string = "Duration"; 620 | 621 | @parseAs(primitiveAnnotationValue("duration")) 622 | public duration: String 623 | } 624 | 625 | export class EnumMemberAnnotation extends Annotation { 626 | public annotationType: string = "EnumMember"; 627 | 628 | @parseAs(primitiveAnnotationValue("enumMember")) 629 | public enumMember: String 630 | } 631 | 632 | export class FloatAnnotation extends Annotation { 633 | public annotationType: string = "Float"; 634 | 635 | @parseAs(primitiveAnnotationValue("float")) 636 | public float: String 637 | } 638 | 639 | export class GuidAnnotation extends Annotation { 640 | public annotationType: string = "Guid"; 641 | 642 | @parseAs(primitiveAnnotationValue("guid")) 643 | public guid: String 644 | } 645 | 646 | export class IntAnnotation extends Annotation { 647 | public annotationType: string = "Int"; 648 | 649 | @parseAs(primitiveAnnotationValue("int")) 650 | public int: String 651 | } 652 | 653 | export class StringAnnotation extends Annotation { 654 | public annotationType: string = "String"; 655 | 656 | @parseAs(primitiveAnnotationValue("string")) 657 | public string: String 658 | } 659 | 660 | export class TimeOfDayAnnotation extends Annotation { 661 | public annotationType: string = "TimeOfDay"; 662 | 663 | @parseAs(primitiveAnnotationValue("timeOfDay")) 664 | public timeOfDay: String 665 | } 666 | 667 | export class PropertyPathAnnotation extends Annotation { 668 | public annotationType: string = "PropertyPath"; 669 | 670 | @parseAs(primitiveAnnotationValue("propertyPath")) 671 | public propertyPaths: String 672 | } 673 | 674 | export class NavigationPropertyPathAnnotation extends Annotation { 675 | public annotationType: string = "NavigationPropertyPath"; 676 | 677 | @parseAs(primitiveAnnotationValue("propertyPath")) 678 | public navigationPropertyPaths: String 679 | } 680 | 681 | export class AnnotationPathAnnotation extends Annotation { 682 | public annotationType: string = "AnnotationPath"; 683 | 684 | @parseAs(primitiveAnnotationValue("annotationPath")) 685 | public annotationPaths: String 686 | } 687 | 688 | export class NullAnnotation extends Annotation { 689 | public annotationType: string = "Null"; 690 | 691 | @parseAs(primitiveAnnotationValue("null")) 692 | public null: Array 693 | } 694 | 695 | 696 | export const AnnotationTypes = { 697 | binary: BinaryAnnotation, 698 | bool: BoolAnnotation, 699 | date: DateAnnotation, 700 | dateTimeOffset: DateTimeOffsetAnnotation, 701 | decimal: DecimalAnnotation, 702 | duration: DurationAnnotation, 703 | enumMember: EnumMemberAnnotation, 704 | float: FloatAnnotation, 705 | guid: GuidAnnotation, 706 | int: IntAnnotation, 707 | string: StringAnnotation, 708 | timeOfDay: TimeOfDayAnnotation, 709 | propertyPath: PropertyPathAnnotation, 710 | navigationPropertyPath: NavigationPropertyPathAnnotation, 711 | annotationPath: AnnotationPathAnnotation, 712 | null: NullAnnotation 713 | } 714 | } 715 | 716 | 717 | -------------------------------------------------------------------------------- /src/metacode.ts: -------------------------------------------------------------------------------- 1 | function isFunction(o: any) { 2 | return "function" === typeof o 3 | } 4 | function isUndefined(o: any) { 5 | return o === undefined 6 | } 7 | 8 | const definitionPropName = 'definition'; 9 | 10 | export class MemberAttribute { 11 | constructor(protected attributeName: string) { } 12 | 13 | private registerMember(target: Object, key: string) { 14 | var def = target[definitionPropName] = target[definitionPropName] || {}; 15 | let md = (def.members || []) 16 | if (md.indexOf(key) < 0) { 17 | md.push(key) 18 | } 19 | 20 | def.members = md 21 | } 22 | 23 | getDecoratorValue(target:Object, key:string, presentedValue?: any) { 24 | return presentedValue 25 | } 26 | 27 | decorate(value?:any):Function { 28 | return (target:Object, key: string, descriptor?: Object) => { 29 | this.registerMember(target, key) 30 | var decoratorValue = this.getDecoratorValue(target, key, value) 31 | 32 | target[definitionPropName][this.attributeName] = target[definitionPropName][this.attributeName] || {} 33 | target[definitionPropName][this.attributeName][key] = decoratorValue; 34 | } 35 | } 36 | 37 | get decorator(): Function { 38 | return this.decorate() 39 | } 40 | 41 | static getMembers(target: Function | Object) { 42 | return target[definitionPropName].members 43 | } 44 | 45 | static getAttributeValue(target: Object, memberName: string, attributeName: string) { 46 | return ((target[definitionPropName] || {})[attributeName] || {})[memberName] 47 | } 48 | 49 | } 50 | 51 | export class AttributeFunctionChain { 52 | private steps: Array = [] 53 | constructor(...steps: Array) { 54 | this.steps = steps 55 | } 56 | 57 | invoke(definition, instance) { 58 | var result = definition 59 | this.steps.forEach(fn => { 60 | result = fn(result, instance) 61 | }) 62 | return result 63 | } 64 | } 65 | 66 | export class ParseAttribute extends MemberAttribute { 67 | constructor() { 68 | super("serialize") 69 | } 70 | 71 | getDecoratorValue(target:Object, key:string, presentedValue?: any) { 72 | if (!isUndefined(presentedValue)) { 73 | return presentedValue 74 | } 75 | return new AttributeFunctionChain( 76 | d => d[key] 77 | ) 78 | } 79 | 80 | 81 | } 82 | 83 | export let required = new MemberAttribute("required").decorate(true) 84 | export let defaultValueAttribute = new MemberAttribute("defaultValue") 85 | export let defaultValue = defaultValueAttribute.decorate.bind(defaultValueAttribute) 86 | export let parseAttribute = new ParseAttribute() 87 | export let parse = parseAttribute.decorator 88 | export let parseAs = parseAttribute.decorate.bind(parseAttribute) 89 | export let typeArgument = new MemberAttribute("typeArgument") 90 | 91 | -------------------------------------------------------------------------------- /tests/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4.0", 3 | "reference": [ 4 | { 5 | "uri": "http://docs.oasis-open.org/odata/odata/v4.0/os/vocabularies/Org.OData.Core.V1.xml", 6 | "include": [ 7 | { 8 | "namespace": "Org.OData.Core.V1", 9 | "alias": "Core" 10 | } 11 | ] 12 | }, 13 | { 14 | "uri": "http://docs.oasis-open.org/odata/odata/v4.0/os/vocabularies/Org.OData.Measures.V1.xml", 15 | "include": [ 16 | { 17 | "alias": "UoM", 18 | "namespace": "Org.OData.Measures.V1" 19 | } 20 | ] 21 | } 22 | ], 23 | "dataServices": { 24 | "schema": [ 25 | { 26 | "namespace": "NorthwindModel", 27 | "entityType": [ 28 | { 29 | "name": "Category", 30 | "key": [ 31 | { 32 | "propertyRef": [ 33 | { 34 | "name": "CategoryID" 35 | } 36 | ] 37 | } 38 | ], 39 | "property": [ 40 | { 41 | "name": "CategoryID", 42 | "type": "Edm.Int32", 43 | "nullable": "false" 44 | }, 45 | { 46 | "name": "CategoryName", 47 | "type": "Edm.String", 48 | "nullable": "false", 49 | "maxLength": "15" 50 | }, 51 | { 52 | "name": "Description", 53 | "type": "Edm.String", 54 | "maxLength": "max" 55 | }, 56 | { 57 | "name": "Picture", 58 | "type": "Edm.Binary", 59 | "maxLength": "max" 60 | } 61 | ], 62 | "navigationProperty": [ 63 | { 64 | "name": "Products", 65 | "type": "Collection(NorthwindModel.Product)", 66 | "partner": "Category" 67 | } 68 | ] 69 | }, 70 | { 71 | "name": "CustomerDemographic", 72 | "key": [ 73 | { 74 | "propertyRef": [ 75 | { 76 | "name": "CustomerTypeID" 77 | } 78 | ] 79 | } 80 | ], 81 | "property": [ 82 | { 83 | "name": "CustomerTypeID", 84 | "type": "Edm.String", 85 | "nullable": "false", 86 | "maxLength": "10" 87 | }, 88 | { 89 | "name": "CustomerDesc", 90 | "type": "Edm.String", 91 | "maxLength": "max" 92 | } 93 | ], 94 | "navigationProperty": [ 95 | { 96 | "name": "Customers", 97 | "type": "Collection(NorthwindModel.Customer)", 98 | "partner": "CustomerDemographics" 99 | } 100 | ] 101 | }, 102 | { 103 | "name": "Customer", 104 | "key": [ 105 | { 106 | "propertyRef": [ 107 | { 108 | "name": "CustomerID" 109 | } 110 | ] 111 | } 112 | ], 113 | "property": [ 114 | { 115 | "name": "CustomerID", 116 | "type": "Edm.String", 117 | "nullable": "false", 118 | "maxLength": "5" 119 | }, 120 | { 121 | "name": "CompanyName", 122 | "type": "Edm.String", 123 | "nullable": "false", 124 | "maxLength": "40" 125 | }, 126 | { 127 | "name": "ContactName", 128 | "type": "Edm.String", 129 | "maxLength": "30" 130 | }, 131 | { 132 | "name": "ContactTitle", 133 | "type": "Edm.String", 134 | "maxLength": "30" 135 | }, 136 | { 137 | "name": "Address", 138 | "type": "Edm.String", 139 | "maxLength": "60" 140 | }, 141 | { 142 | "name": "City", 143 | "type": "Edm.String", 144 | "maxLength": "15" 145 | }, 146 | { 147 | "name": "Region", 148 | "type": "Edm.String", 149 | "maxLength": "15" 150 | }, 151 | { 152 | "name": "PostalCode", 153 | "type": "Edm.String", 154 | "maxLength": "10" 155 | }, 156 | { 157 | "name": "Country", 158 | "type": "Edm.String", 159 | "maxLength": "15" 160 | }, 161 | { 162 | "name": "Phone", 163 | "type": "Edm.String", 164 | "maxLength": "24" 165 | }, 166 | { 167 | "name": "Fax", 168 | "type": "Edm.String", 169 | "maxLength": "24" 170 | } 171 | ], 172 | "navigationProperty": [ 173 | { 174 | "name": "Orders", 175 | "type": "Collection(NorthwindModel.Order)", 176 | "partner": "Customer" 177 | }, 178 | { 179 | "name": "CustomerDemographics", 180 | "type": "Collection(NorthwindModel.CustomerDemographic)", 181 | "partner": "Customers" 182 | } 183 | ] 184 | }, 185 | { 186 | "name": "Employee", 187 | "key": [ 188 | { 189 | "propertyRef": [ 190 | { 191 | "name": "EmployeeID" 192 | } 193 | ] 194 | } 195 | ], 196 | "property": [ 197 | { 198 | "name": "EmployeeID", 199 | "type": "Edm.Int32", 200 | "nullable": "false" 201 | }, 202 | { 203 | "name": "LastName", 204 | "type": "Edm.String", 205 | "nullable": "false", 206 | "maxLength": "20" 207 | }, 208 | { 209 | "name": "FirstName", 210 | "type": "Edm.String", 211 | "nullable": "false", 212 | "maxLength": "10" 213 | }, 214 | { 215 | "name": "Title", 216 | "type": "Edm.String", 217 | "maxLength": "30" 218 | }, 219 | { 220 | "name": "TitleOfCourtesy", 221 | "type": "Edm.String", 222 | "maxLength": "25" 223 | }, 224 | { 225 | "name": "BirthDate", 226 | "type": "Edm.DateTimeOffset" 227 | }, 228 | { 229 | "name": "HireDate", 230 | "type": "Edm.DateTimeOffset" 231 | }, 232 | { 233 | "name": "Address", 234 | "type": "Edm.String", 235 | "maxLength": "60" 236 | }, 237 | { 238 | "name": "City", 239 | "type": "Edm.String", 240 | "maxLength": "15" 241 | }, 242 | { 243 | "name": "Region", 244 | "type": "Edm.String", 245 | "maxLength": "15" 246 | }, 247 | { 248 | "name": "PostalCode", 249 | "type": "Edm.String", 250 | "maxLength": "10" 251 | }, 252 | { 253 | "name": "Country", 254 | "type": "Edm.String", 255 | "maxLength": "15" 256 | }, 257 | { 258 | "name": "HomePhone", 259 | "type": "Edm.String", 260 | "maxLength": "24" 261 | }, 262 | { 263 | "name": "Extension", 264 | "type": "Edm.String", 265 | "maxLength": "4" 266 | }, 267 | { 268 | "name": "Photo", 269 | "type": "Edm.Binary", 270 | "maxLength": "max" 271 | }, 272 | { 273 | "name": "Notes", 274 | "type": "Edm.String", 275 | "maxLength": "max" 276 | }, 277 | { 278 | "name": "ReportsTo", 279 | "type": "Edm.Int32" 280 | }, 281 | { 282 | "name": "PhotoPath", 283 | "type": "Edm.String", 284 | "maxLength": "255" 285 | } 286 | ], 287 | "navigationProperty": [ 288 | { 289 | "name": "Employees1", 290 | "type": "Collection(NorthwindModel.Employee)", 291 | "partner": "Employee1" 292 | }, 293 | { 294 | "name": "Employee1", 295 | "type": "NorthwindModel.Employee", 296 | "partner": "Employees1", 297 | "referentialConstraint": [ 298 | { 299 | "property": "ReportsTo", 300 | "referencedProperty": "EmployeeID" 301 | } 302 | ] 303 | }, 304 | { 305 | "name": "Orders", 306 | "type": "Collection(NorthwindModel.Order)", 307 | "partner": "Employee" 308 | }, 309 | { 310 | "name": "Territories", 311 | "type": "Collection(NorthwindModel.Territory)", 312 | "partner": "Employees" 313 | } 314 | ] 315 | }, 316 | { 317 | "name": "Order_Detail", 318 | "key": [ 319 | { 320 | "propertyRef": [ 321 | { 322 | "name": "OrderID" 323 | }, 324 | { 325 | "name": "ProductID" 326 | } 327 | ] 328 | } 329 | ], 330 | "property": [ 331 | { 332 | "name": "OrderID", 333 | "type": "Edm.Int32", 334 | "nullable": "false" 335 | }, 336 | { 337 | "name": "ProductID", 338 | "type": "Edm.Int32", 339 | "nullable": "false" 340 | }, 341 | { 342 | "name": "UnitPrice", 343 | "type": "Edm.Decimal", 344 | "nullable": "false", 345 | "precision": "19", 346 | "scale": "4" 347 | }, 348 | { 349 | "name": "Quantity", 350 | "type": "Edm.Int16", 351 | "nullable": "false" 352 | }, 353 | { 354 | "name": "Discount", 355 | "type": "Edm.Single", 356 | "nullable": "false" 357 | } 358 | ], 359 | "navigationProperty": [ 360 | { 361 | "name": "Order", 362 | "type": "NorthwindModel.Order", 363 | "nullable": "false", 364 | "partner": "Order_Details", 365 | "referentialConstraint": [ 366 | { 367 | "property": "OrderID", 368 | "referencedProperty": "OrderID" 369 | } 370 | ] 371 | }, 372 | { 373 | "name": "Product", 374 | "type": "NorthwindModel.Product", 375 | "nullable": "false", 376 | "partner": "Order_Details", 377 | "referentialConstraint": [ 378 | { 379 | "property": "ProductID", 380 | "referencedProperty": "ProductID" 381 | } 382 | ] 383 | } 384 | ] 385 | }, 386 | { 387 | "name": "Order", 388 | "key": [ 389 | { 390 | "propertyRef": [ 391 | { 392 | "name": "OrderID" 393 | } 394 | ] 395 | } 396 | ], 397 | "property": [ 398 | { 399 | "name": "OrderID", 400 | "type": "Edm.Int32", 401 | "nullable": "false" 402 | }, 403 | { 404 | "name": "CustomerID", 405 | "type": "Edm.String", 406 | "maxLength": "5" 407 | }, 408 | { 409 | "name": "EmployeeID", 410 | "type": "Edm.Int32" 411 | }, 412 | { 413 | "name": "OrderDate", 414 | "type": "Edm.DateTimeOffset" 415 | }, 416 | { 417 | "name": "RequiredDate", 418 | "type": "Edm.DateTimeOffset" 419 | }, 420 | { 421 | "name": "ShippedDate", 422 | "type": "Edm.DateTimeOffset" 423 | }, 424 | { 425 | "name": "ShipVia", 426 | "type": "Edm.Int32" 427 | }, 428 | { 429 | "name": "Freight", 430 | "type": "Edm.Decimal", 431 | "precision": "19", 432 | "scale": "4" 433 | }, 434 | { 435 | "name": "ShipName", 436 | "type": "Edm.String", 437 | "maxLength": "40" 438 | }, 439 | { 440 | "name": "ShipAddress", 441 | "type": "Edm.String", 442 | "maxLength": "60" 443 | }, 444 | { 445 | "name": "ShipCity", 446 | "type": "Edm.String", 447 | "maxLength": "15" 448 | }, 449 | { 450 | "name": "ShipRegion", 451 | "type": "Edm.String", 452 | "maxLength": "15" 453 | }, 454 | { 455 | "name": "ShipPostalCode", 456 | "type": "Edm.String", 457 | "maxLength": "10" 458 | }, 459 | { 460 | "name": "ShipCountry", 461 | "type": "Edm.String", 462 | "maxLength": "15" 463 | } 464 | ], 465 | "navigationProperty": [ 466 | { 467 | "name": "Customer", 468 | "type": "NorthwindModel.Customer", 469 | "partner": "Orders", 470 | "referentialConstraint": [ 471 | { 472 | "property": "CustomerID", 473 | "referencedProperty": "CustomerID" 474 | } 475 | ] 476 | }, 477 | { 478 | "name": "Employee", 479 | "type": "NorthwindModel.Employee", 480 | "partner": "Orders", 481 | "referentialConstraint": [ 482 | { 483 | "property": "EmployeeID", 484 | "referencedProperty": "EmployeeID" 485 | } 486 | ] 487 | }, 488 | { 489 | "name": "Order_Details", 490 | "type": "Collection(NorthwindModel.Order_Detail)", 491 | "partner": "Order" 492 | }, 493 | { 494 | "name": "Shipper", 495 | "type": "NorthwindModel.Shipper", 496 | "partner": "Orders", 497 | "referentialConstraint": [ 498 | { 499 | "property": "ShipVia", 500 | "referencedProperty": "ShipperID" 501 | } 502 | ] 503 | } 504 | ] 505 | }, 506 | { 507 | "name": "Product", 508 | "key": [ 509 | { 510 | "propertyRef": [ 511 | { 512 | "name": "ProductID" 513 | } 514 | ] 515 | } 516 | ], 517 | "property": [ 518 | { 519 | "name": "ProductID", 520 | "type": "Edm.Int32", 521 | "nullable": "false" 522 | }, 523 | { 524 | "name": "ProductName", 525 | "type": "Edm.String", 526 | "nullable": "false", 527 | "maxLength": "40" 528 | }, 529 | { 530 | "name": "SupplierID", 531 | "type": "Edm.Int32" 532 | }, 533 | { 534 | "name": "CategoryID", 535 | "type": "Edm.Int32" 536 | }, 537 | { 538 | "name": "QuantityPerUnit", 539 | "type": "Edm.String", 540 | "maxLength": "20" 541 | }, 542 | { 543 | "name": "UnitPrice", 544 | "type": "Edm.Decimal", 545 | "precision": "19", 546 | "scale": "4" 547 | }, 548 | { 549 | "name": "UnitsInStock", 550 | "type": "Edm.Int16" 551 | }, 552 | { 553 | "name": "UnitsOnOrder", 554 | "type": "Edm.Int16" 555 | }, 556 | { 557 | "name": "ReorderLevel", 558 | "type": "Edm.Int16" 559 | }, 560 | { 561 | "name": "Discontinued", 562 | "type": "Edm.Boolean", 563 | "nullable": "false" 564 | } 565 | ], 566 | "navigationProperty": [ 567 | { 568 | "name": "Category", 569 | "type": "NorthwindModel.Category", 570 | "partner": "Products", 571 | "referentialConstraint": [ 572 | { 573 | "property": "CategoryID", 574 | "referencedProperty": "CategoryID" 575 | } 576 | ] 577 | }, 578 | { 579 | "name": "Order_Details", 580 | "type": "Collection(NorthwindModel.Order_Detail)", 581 | "partner": "Product" 582 | }, 583 | { 584 | "name": "Supplier", 585 | "type": "NorthwindModel.Supplier", 586 | "partner": "Products", 587 | "referentialConstraint": [ 588 | { 589 | "property": "SupplierID", 590 | "referencedProperty": "SupplierID" 591 | } 592 | ] 593 | } 594 | ] 595 | }, 596 | { 597 | "name": "Region", 598 | "key": [ 599 | { 600 | "propertyRef": [ 601 | { 602 | "name": "RegionID" 603 | } 604 | ] 605 | } 606 | ], 607 | "property": [ 608 | { 609 | "name": "RegionID", 610 | "type": "Edm.Int32", 611 | "nullable": "false" 612 | }, 613 | { 614 | "name": "RegionDescription", 615 | "type": "Edm.String", 616 | "nullable": "false", 617 | "maxLength": "50" 618 | } 619 | ], 620 | "navigationProperty": [ 621 | { 622 | "name": "Territories", 623 | "type": "Collection(NorthwindModel.Territory)", 624 | "partner": "Region" 625 | } 626 | ] 627 | }, 628 | { 629 | "name": "Shipper", 630 | "key": [ 631 | { 632 | "propertyRef": [ 633 | { 634 | "name": "ShipperID" 635 | } 636 | ] 637 | } 638 | ], 639 | "property": [ 640 | { 641 | "name": "ShipperID", 642 | "type": "Edm.Int32", 643 | "nullable": "false" 644 | }, 645 | { 646 | "name": "CompanyName", 647 | "type": "Edm.String", 648 | "nullable": "false", 649 | "maxLength": "40" 650 | }, 651 | { 652 | "name": "Phone", 653 | "type": "Edm.String", 654 | "maxLength": "24" 655 | } 656 | ], 657 | "navigationProperty": [ 658 | { 659 | "name": "Orders", 660 | "type": "Collection(NorthwindModel.Order)", 661 | "partner": "Shipper" 662 | } 663 | ] 664 | }, 665 | { 666 | "name": "Supplier", 667 | "key": [ 668 | { 669 | "propertyRef": [ 670 | { 671 | "name": "SupplierID" 672 | } 673 | ] 674 | } 675 | ], 676 | "property": [ 677 | { 678 | "name": "SupplierID", 679 | "type": "Edm.Int32", 680 | "nullable": "false" 681 | }, 682 | { 683 | "name": "CompanyName", 684 | "type": "Edm.String", 685 | "nullable": "false", 686 | "maxLength": "40" 687 | }, 688 | { 689 | "name": "ContactName", 690 | "type": "Edm.String", 691 | "maxLength": "30" 692 | }, 693 | { 694 | "name": "ContactTitle", 695 | "type": "Edm.String", 696 | "maxLength": "30" 697 | }, 698 | { 699 | "name": "Address", 700 | "type": "Edm.String", 701 | "maxLength": "60" 702 | }, 703 | { 704 | "name": "City", 705 | "type": "Edm.String", 706 | "maxLength": "15" 707 | }, 708 | { 709 | "name": "Region", 710 | "type": "Edm.String", 711 | "maxLength": "15" 712 | }, 713 | { 714 | "name": "PostalCode", 715 | "type": "Edm.String", 716 | "maxLength": "10" 717 | }, 718 | { 719 | "name": "Country", 720 | "type": "Edm.String", 721 | "maxLength": "15" 722 | }, 723 | { 724 | "name": "Phone", 725 | "type": "Edm.String", 726 | "maxLength": "24" 727 | }, 728 | { 729 | "name": "Fax", 730 | "type": "Edm.String", 731 | "maxLength": "24" 732 | }, 733 | { 734 | "name": "HomePage", 735 | "type": "Edm.String", 736 | "maxLength": "max" 737 | } 738 | ], 739 | "navigationProperty": [ 740 | { 741 | "name": "Products", 742 | "type": "Collection(NorthwindModel.Product)", 743 | "partner": "Supplier" 744 | } 745 | ] 746 | }, 747 | { 748 | "name": "Territory", 749 | "key": [ 750 | { 751 | "propertyRef": [ 752 | { 753 | "name": "TerritoryID" 754 | } 755 | ] 756 | } 757 | ], 758 | "property": [ 759 | { 760 | "name": "TerritoryID", 761 | "type": "Edm.String", 762 | "nullable": "false", 763 | "maxLength": "20" 764 | }, 765 | { 766 | "name": "TerritoryDescription", 767 | "type": "Edm.String", 768 | "nullable": "false", 769 | "maxLength": "50" 770 | }, 771 | { 772 | "name": "RegionID", 773 | "type": "Edm.Int32", 774 | "nullable": "false" 775 | } 776 | ], 777 | "navigationProperty": [ 778 | { 779 | "name": "Region", 780 | "type": "NorthwindModel.Region", 781 | "nullable": "false", 782 | "partner": "Territories", 783 | "referentialConstraint": [ 784 | { 785 | "property": "RegionID", 786 | "referencedProperty": "RegionID" 787 | } 788 | ] 789 | }, 790 | { 791 | "name": "Employees", 792 | "type": "Collection(NorthwindModel.Employee)", 793 | "partner": "Territories" 794 | } 795 | ] 796 | }, 797 | { 798 | "name": "Alphabetical_list_of_product", 799 | "key": [ 800 | { 801 | "propertyRef": [ 802 | { 803 | "name": "CategoryName" 804 | }, 805 | { 806 | "name": "Discontinued" 807 | }, 808 | { 809 | "name": "ProductID" 810 | }, 811 | { 812 | "name": "ProductName" 813 | } 814 | ] 815 | } 816 | ], 817 | "property": [ 818 | { 819 | "name": "ProductID", 820 | "type": "Edm.Int32", 821 | "nullable": "false" 822 | }, 823 | { 824 | "name": "ProductName", 825 | "type": "Edm.String", 826 | "nullable": "false", 827 | "maxLength": "40" 828 | }, 829 | { 830 | "name": "SupplierID", 831 | "type": "Edm.Int32" 832 | }, 833 | { 834 | "name": "CategoryID", 835 | "type": "Edm.Int32" 836 | }, 837 | { 838 | "name": "QuantityPerUnit", 839 | "type": "Edm.String", 840 | "maxLength": "20" 841 | }, 842 | { 843 | "name": "UnitPrice", 844 | "type": "Edm.Decimal", 845 | "precision": "19", 846 | "scale": "4" 847 | }, 848 | { 849 | "name": "UnitsInStock", 850 | "type": "Edm.Int16" 851 | }, 852 | { 853 | "name": "UnitsOnOrder", 854 | "type": "Edm.Int16" 855 | }, 856 | { 857 | "name": "ReorderLevel", 858 | "type": "Edm.Int16" 859 | }, 860 | { 861 | "name": "Discontinued", 862 | "type": "Edm.Boolean", 863 | "nullable": "false" 864 | }, 865 | { 866 | "name": "CategoryName", 867 | "type": "Edm.String", 868 | "nullable": "false", 869 | "maxLength": "15" 870 | } 871 | ] 872 | }, 873 | { 874 | "name": "Category_Sales_for_1997", 875 | "key": [ 876 | { 877 | "propertyRef": [ 878 | { 879 | "name": "CategoryName" 880 | } 881 | ] 882 | } 883 | ], 884 | "property": [ 885 | { 886 | "name": "CategoryName", 887 | "type": "Edm.String", 888 | "nullable": "false", 889 | "maxLength": "15" 890 | }, 891 | { 892 | "name": "CategorySales", 893 | "type": "Edm.Decimal", 894 | "precision": "19", 895 | "scale": "4" 896 | } 897 | ] 898 | }, 899 | { 900 | "name": "Current_Product_List", 901 | "key": [ 902 | { 903 | "propertyRef": [ 904 | { 905 | "name": "ProductID" 906 | }, 907 | { 908 | "name": "ProductName" 909 | } 910 | ] 911 | } 912 | ], 913 | "property": [ 914 | { 915 | "name": "ProductID", 916 | "type": "Edm.Int32", 917 | "nullable": "false" 918 | }, 919 | { 920 | "name": "ProductName", 921 | "type": "Edm.String", 922 | "nullable": "false", 923 | "maxLength": "40" 924 | } 925 | ] 926 | }, 927 | { 928 | "name": "Customer_and_Suppliers_by_City", 929 | "key": [ 930 | { 931 | "propertyRef": [ 932 | { 933 | "name": "CompanyName" 934 | }, 935 | { 936 | "name": "Relationship" 937 | } 938 | ] 939 | } 940 | ], 941 | "property": [ 942 | { 943 | "name": "City", 944 | "type": "Edm.String", 945 | "maxLength": "15" 946 | }, 947 | { 948 | "name": "CompanyName", 949 | "type": "Edm.String", 950 | "nullable": "false", 951 | "maxLength": "40" 952 | }, 953 | { 954 | "name": "ContactName", 955 | "type": "Edm.String", 956 | "maxLength": "30" 957 | }, 958 | { 959 | "name": "Relationship", 960 | "type": "Edm.String", 961 | "nullable": "false", 962 | "maxLength": "9", 963 | "unicode": "false" 964 | } 965 | ] 966 | }, 967 | { 968 | "name": "Invoice", 969 | "key": [ 970 | { 971 | "propertyRef": [ 972 | { 973 | "name": "CustomerName" 974 | }, 975 | { 976 | "name": "Discount" 977 | }, 978 | { 979 | "name": "OrderID" 980 | }, 981 | { 982 | "name": "ProductID" 983 | }, 984 | { 985 | "name": "ProductName" 986 | }, 987 | { 988 | "name": "Quantity" 989 | }, 990 | { 991 | "name": "Salesperson" 992 | }, 993 | { 994 | "name": "ShipperName" 995 | }, 996 | { 997 | "name": "UnitPrice" 998 | } 999 | ] 1000 | } 1001 | ], 1002 | "property": [ 1003 | { 1004 | "name": "ShipName", 1005 | "type": "Edm.String", 1006 | "maxLength": "40" 1007 | }, 1008 | { 1009 | "name": "ShipAddress", 1010 | "type": "Edm.String", 1011 | "maxLength": "60" 1012 | }, 1013 | { 1014 | "name": "ShipCity", 1015 | "type": "Edm.String", 1016 | "maxLength": "15" 1017 | }, 1018 | { 1019 | "name": "ShipRegion", 1020 | "type": "Edm.String", 1021 | "maxLength": "15" 1022 | }, 1023 | { 1024 | "name": "ShipPostalCode", 1025 | "type": "Edm.String", 1026 | "maxLength": "10" 1027 | }, 1028 | { 1029 | "name": "ShipCountry", 1030 | "type": "Edm.String", 1031 | "maxLength": "15" 1032 | }, 1033 | { 1034 | "name": "CustomerID", 1035 | "type": "Edm.String", 1036 | "maxLength": "5" 1037 | }, 1038 | { 1039 | "name": "CustomerName", 1040 | "type": "Edm.String", 1041 | "nullable": "false", 1042 | "maxLength": "40" 1043 | }, 1044 | { 1045 | "name": "Address", 1046 | "type": "Edm.String", 1047 | "maxLength": "60" 1048 | }, 1049 | { 1050 | "name": "City", 1051 | "type": "Edm.String", 1052 | "maxLength": "15" 1053 | }, 1054 | { 1055 | "name": "Region", 1056 | "type": "Edm.String", 1057 | "maxLength": "15" 1058 | }, 1059 | { 1060 | "name": "PostalCode", 1061 | "type": "Edm.String", 1062 | "maxLength": "10" 1063 | }, 1064 | { 1065 | "name": "Country", 1066 | "type": "Edm.String", 1067 | "maxLength": "15" 1068 | }, 1069 | { 1070 | "name": "Salesperson", 1071 | "type": "Edm.String", 1072 | "nullable": "false", 1073 | "maxLength": "31" 1074 | }, 1075 | { 1076 | "name": "OrderID", 1077 | "type": "Edm.Int32", 1078 | "nullable": "false" 1079 | }, 1080 | { 1081 | "name": "OrderDate", 1082 | "type": "Edm.DateTimeOffset" 1083 | }, 1084 | { 1085 | "name": "RequiredDate", 1086 | "type": "Edm.DateTimeOffset" 1087 | }, 1088 | { 1089 | "name": "ShippedDate", 1090 | "type": "Edm.DateTimeOffset" 1091 | }, 1092 | { 1093 | "name": "ShipperName", 1094 | "type": "Edm.String", 1095 | "nullable": "false", 1096 | "maxLength": "40" 1097 | }, 1098 | { 1099 | "name": "ProductID", 1100 | "type": "Edm.Int32", 1101 | "nullable": "false" 1102 | }, 1103 | { 1104 | "name": "ProductName", 1105 | "type": "Edm.String", 1106 | "nullable": "false", 1107 | "maxLength": "40" 1108 | }, 1109 | { 1110 | "name": "UnitPrice", 1111 | "type": "Edm.Decimal", 1112 | "nullable": "false", 1113 | "precision": "19", 1114 | "scale": "4" 1115 | }, 1116 | { 1117 | "name": "Quantity", 1118 | "type": "Edm.Int16", 1119 | "nullable": "false" 1120 | }, 1121 | { 1122 | "name": "Discount", 1123 | "type": "Edm.Single", 1124 | "nullable": "false" 1125 | }, 1126 | { 1127 | "name": "ExtendedPrice", 1128 | "type": "Edm.Decimal", 1129 | "precision": "19", 1130 | "scale": "4" 1131 | }, 1132 | { 1133 | "name": "Freight", 1134 | "type": "Edm.Decimal", 1135 | "precision": "19", 1136 | "scale": "4" 1137 | } 1138 | ] 1139 | }, 1140 | { 1141 | "name": "Order_Details_Extended", 1142 | "key": [ 1143 | { 1144 | "propertyRef": [ 1145 | { 1146 | "name": "Discount" 1147 | }, 1148 | { 1149 | "name": "OrderID" 1150 | }, 1151 | { 1152 | "name": "ProductID" 1153 | }, 1154 | { 1155 | "name": "ProductName" 1156 | }, 1157 | { 1158 | "name": "Quantity" 1159 | }, 1160 | { 1161 | "name": "UnitPrice" 1162 | } 1163 | ] 1164 | } 1165 | ], 1166 | "property": [ 1167 | { 1168 | "name": "OrderID", 1169 | "type": "Edm.Int32", 1170 | "nullable": "false" 1171 | }, 1172 | { 1173 | "name": "ProductID", 1174 | "type": "Edm.Int32", 1175 | "nullable": "false" 1176 | }, 1177 | { 1178 | "name": "ProductName", 1179 | "type": "Edm.String", 1180 | "nullable": "false", 1181 | "maxLength": "40" 1182 | }, 1183 | { 1184 | "name": "UnitPrice", 1185 | "type": "Edm.Decimal", 1186 | "nullable": "false", 1187 | "precision": "19", 1188 | "scale": "4" 1189 | }, 1190 | { 1191 | "name": "Quantity", 1192 | "type": "Edm.Int16", 1193 | "nullable": "false" 1194 | }, 1195 | { 1196 | "name": "Discount", 1197 | "type": "Edm.Single", 1198 | "nullable": "false" 1199 | }, 1200 | { 1201 | "name": "ExtendedPrice", 1202 | "type": "Edm.Decimal", 1203 | "precision": "19", 1204 | "scale": "4" 1205 | } 1206 | ] 1207 | }, 1208 | { 1209 | "name": "Order_Subtotal", 1210 | "key": [ 1211 | { 1212 | "propertyRef": [ 1213 | { 1214 | "name": "OrderID" 1215 | } 1216 | ] 1217 | } 1218 | ], 1219 | "property": [ 1220 | { 1221 | "name": "OrderID", 1222 | "type": "Edm.Int32", 1223 | "nullable": "false" 1224 | }, 1225 | { 1226 | "name": "Subtotal", 1227 | "type": "Edm.Decimal", 1228 | "precision": "19", 1229 | "scale": "4" 1230 | } 1231 | ] 1232 | }, 1233 | { 1234 | "name": "Orders_Qry", 1235 | "key": [ 1236 | { 1237 | "propertyRef": [ 1238 | { 1239 | "name": "CompanyName" 1240 | }, 1241 | { 1242 | "name": "OrderID" 1243 | } 1244 | ] 1245 | } 1246 | ], 1247 | "property": [ 1248 | { 1249 | "name": "OrderID", 1250 | "type": "Edm.Int32", 1251 | "nullable": "false" 1252 | }, 1253 | { 1254 | "name": "CustomerID", 1255 | "type": "Edm.String", 1256 | "maxLength": "5" 1257 | }, 1258 | { 1259 | "name": "EmployeeID", 1260 | "type": "Edm.Int32" 1261 | }, 1262 | { 1263 | "name": "OrderDate", 1264 | "type": "Edm.DateTimeOffset" 1265 | }, 1266 | { 1267 | "name": "RequiredDate", 1268 | "type": "Edm.DateTimeOffset" 1269 | }, 1270 | { 1271 | "name": "ShippedDate", 1272 | "type": "Edm.DateTimeOffset" 1273 | }, 1274 | { 1275 | "name": "ShipVia", 1276 | "type": "Edm.Int32" 1277 | }, 1278 | { 1279 | "name": "Freight", 1280 | "type": "Edm.Decimal", 1281 | "precision": "19", 1282 | "scale": "4" 1283 | }, 1284 | { 1285 | "name": "ShipName", 1286 | "type": "Edm.String", 1287 | "maxLength": "40" 1288 | }, 1289 | { 1290 | "name": "ShipAddress", 1291 | "type": "Edm.String", 1292 | "maxLength": "60" 1293 | }, 1294 | { 1295 | "name": "ShipCity", 1296 | "type": "Edm.String", 1297 | "maxLength": "15" 1298 | }, 1299 | { 1300 | "name": "ShipRegion", 1301 | "type": "Edm.String", 1302 | "maxLength": "15" 1303 | }, 1304 | { 1305 | "name": "ShipPostalCode", 1306 | "type": "Edm.String", 1307 | "maxLength": "10" 1308 | }, 1309 | { 1310 | "name": "ShipCountry", 1311 | "type": "Edm.String", 1312 | "maxLength": "15" 1313 | }, 1314 | { 1315 | "name": "CompanyName", 1316 | "type": "Edm.String", 1317 | "nullable": "false", 1318 | "maxLength": "40" 1319 | }, 1320 | { 1321 | "name": "Address", 1322 | "type": "Edm.String", 1323 | "maxLength": "60" 1324 | }, 1325 | { 1326 | "name": "City", 1327 | "type": "Edm.String", 1328 | "maxLength": "15" 1329 | }, 1330 | { 1331 | "name": "Region", 1332 | "type": "Edm.String", 1333 | "maxLength": "15" 1334 | }, 1335 | { 1336 | "name": "PostalCode", 1337 | "type": "Edm.String", 1338 | "maxLength": "10" 1339 | }, 1340 | { 1341 | "name": "Country", 1342 | "type": "Edm.String", 1343 | "maxLength": "15" 1344 | } 1345 | ] 1346 | }, 1347 | { 1348 | "name": "Product_Sales_for_1997", 1349 | "key": [ 1350 | { 1351 | "propertyRef": [ 1352 | { 1353 | "name": "CategoryName" 1354 | }, 1355 | { 1356 | "name": "ProductName" 1357 | } 1358 | ] 1359 | } 1360 | ], 1361 | "property": [ 1362 | { 1363 | "name": "CategoryName", 1364 | "type": "Edm.String", 1365 | "nullable": "false", 1366 | "maxLength": "15" 1367 | }, 1368 | { 1369 | "name": "ProductName", 1370 | "type": "Edm.String", 1371 | "nullable": "false", 1372 | "maxLength": "40" 1373 | }, 1374 | { 1375 | "name": "ProductSales", 1376 | "type": "Edm.Decimal", 1377 | "precision": "19", 1378 | "scale": "4" 1379 | } 1380 | ] 1381 | }, 1382 | { 1383 | "name": "Products_Above_Average_Price", 1384 | "key": [ 1385 | { 1386 | "propertyRef": [ 1387 | { 1388 | "name": "ProductName" 1389 | } 1390 | ] 1391 | } 1392 | ], 1393 | "property": [ 1394 | { 1395 | "name": "ProductName", 1396 | "type": "Edm.String", 1397 | "nullable": "false", 1398 | "maxLength": "40" 1399 | }, 1400 | { 1401 | "name": "UnitPrice", 1402 | "type": "Edm.Decimal", 1403 | "precision": "19", 1404 | "scale": "4" 1405 | } 1406 | ] 1407 | }, 1408 | { 1409 | "name": "Products_by_Category", 1410 | "key": [ 1411 | { 1412 | "propertyRef": [ 1413 | { 1414 | "name": "CategoryName" 1415 | }, 1416 | { 1417 | "name": "Discontinued" 1418 | }, 1419 | { 1420 | "name": "ProductName" 1421 | } 1422 | ] 1423 | } 1424 | ], 1425 | "property": [ 1426 | { 1427 | "name": "CategoryName", 1428 | "type": "Edm.String", 1429 | "nullable": "false", 1430 | "maxLength": "15" 1431 | }, 1432 | { 1433 | "name": "ProductName", 1434 | "type": "Edm.String", 1435 | "nullable": "false", 1436 | "maxLength": "40" 1437 | }, 1438 | { 1439 | "name": "QuantityPerUnit", 1440 | "type": "Edm.String", 1441 | "maxLength": "20" 1442 | }, 1443 | { 1444 | "name": "UnitsInStock", 1445 | "type": "Edm.Int16" 1446 | }, 1447 | { 1448 | "name": "Discontinued", 1449 | "type": "Edm.Boolean", 1450 | "nullable": "false" 1451 | } 1452 | ] 1453 | }, 1454 | { 1455 | "name": "Sales_by_Category", 1456 | "key": [ 1457 | { 1458 | "propertyRef": [ 1459 | { 1460 | "name": "CategoryID" 1461 | }, 1462 | { 1463 | "name": "CategoryName" 1464 | }, 1465 | { 1466 | "name": "ProductName" 1467 | } 1468 | ] 1469 | } 1470 | ], 1471 | "property": [ 1472 | { 1473 | "name": "CategoryID", 1474 | "type": "Edm.Int32", 1475 | "nullable": "false" 1476 | }, 1477 | { 1478 | "name": "CategoryName", 1479 | "type": "Edm.String", 1480 | "nullable": "false", 1481 | "maxLength": "15" 1482 | }, 1483 | { 1484 | "name": "ProductName", 1485 | "type": "Edm.String", 1486 | "nullable": "false", 1487 | "maxLength": "40" 1488 | }, 1489 | { 1490 | "name": "ProductSales", 1491 | "type": "Edm.Decimal", 1492 | "precision": "19", 1493 | "scale": "4" 1494 | } 1495 | ] 1496 | }, 1497 | { 1498 | "name": "Sales_Totals_by_Amount", 1499 | "key": [ 1500 | { 1501 | "propertyRef": [ 1502 | { 1503 | "name": "CompanyName" 1504 | }, 1505 | { 1506 | "name": "OrderID" 1507 | } 1508 | ] 1509 | } 1510 | ], 1511 | "property": [ 1512 | { 1513 | "name": "SaleAmount", 1514 | "type": "Edm.Decimal", 1515 | "precision": "19", 1516 | "scale": "4" 1517 | }, 1518 | { 1519 | "name": "OrderID", 1520 | "type": "Edm.Int32", 1521 | "nullable": "false" 1522 | }, 1523 | { 1524 | "name": "CompanyName", 1525 | "type": "Edm.String", 1526 | "nullable": "false", 1527 | "maxLength": "40" 1528 | }, 1529 | { 1530 | "name": "ShippedDate", 1531 | "type": "Edm.DateTimeOffset" 1532 | } 1533 | ] 1534 | }, 1535 | { 1536 | "name": "Summary_of_Sales_by_Quarter", 1537 | "key": [ 1538 | { 1539 | "propertyRef": [ 1540 | { 1541 | "name": "OrderID" 1542 | } 1543 | ] 1544 | } 1545 | ], 1546 | "property": [ 1547 | { 1548 | "name": "ShippedDate", 1549 | "type": "Edm.DateTimeOffset" 1550 | }, 1551 | { 1552 | "name": "OrderID", 1553 | "type": "Edm.Int32", 1554 | "nullable": "false" 1555 | }, 1556 | { 1557 | "name": "Subtotal", 1558 | "type": "Edm.Decimal", 1559 | "precision": "19", 1560 | "scale": "4" 1561 | } 1562 | ] 1563 | }, 1564 | { 1565 | "name": "Summary_of_Sales_by_Year", 1566 | "key": [ 1567 | { 1568 | "propertyRef": [ 1569 | { 1570 | "name": "OrderID" 1571 | } 1572 | ] 1573 | } 1574 | ], 1575 | "property": [ 1576 | { 1577 | "name": "ShippedDate", 1578 | "type": "Edm.DateTimeOffset" 1579 | }, 1580 | { 1581 | "name": "OrderID", 1582 | "type": "Edm.Int32", 1583 | "nullable": "false" 1584 | }, 1585 | { 1586 | "name": "Subtotal", 1587 | "type": "Edm.Decimal", 1588 | "precision": "19", 1589 | "scale": "4" 1590 | } 1591 | ] 1592 | } 1593 | ] 1594 | }, 1595 | { 1596 | "namespace": "ODataWebExperimental.Northwind.Model", 1597 | "entityContainer": { 1598 | "name": "NorthwindEntities", 1599 | "entitySet": [ 1600 | { 1601 | "name": "Categories", 1602 | "entityType": "NorthwindModel.Category", 1603 | "navigationPropertyBinding": [ 1604 | { 1605 | "path": "Products", 1606 | "target": "Products" 1607 | } 1608 | ] 1609 | }, 1610 | { 1611 | "name": "CustomerDemographics", 1612 | "entityType": "NorthwindModel.CustomerDemographic", 1613 | "navigationPropertyBinding": [ 1614 | { 1615 | "path": "Customers", 1616 | "target": "Customers" 1617 | } 1618 | ] 1619 | }, 1620 | { 1621 | "name": "Customers", 1622 | "entityType": "NorthwindModel.Customer", 1623 | "navigationPropertyBinding": [ 1624 | { 1625 | "path": "CustomerDemographics", 1626 | "target": "CustomerDemographics" 1627 | }, 1628 | { 1629 | "path": "Orders", 1630 | "target": "Orders" 1631 | } 1632 | ] 1633 | }, 1634 | { 1635 | "name": "Employees", 1636 | "entityType": "NorthwindModel.Employee", 1637 | "navigationPropertyBinding": [ 1638 | { 1639 | "path": "Employees1", 1640 | "target": "Employees" 1641 | }, 1642 | { 1643 | "path": "Employee1", 1644 | "target": "Employees" 1645 | }, 1646 | { 1647 | "path": "Orders", 1648 | "target": "Orders" 1649 | }, 1650 | { 1651 | "path": "Territories", 1652 | "target": "Territories" 1653 | } 1654 | ] 1655 | }, 1656 | { 1657 | "name": "Order_Details", 1658 | "entityType": "NorthwindModel.Order_Detail", 1659 | "navigationPropertyBinding": [ 1660 | { 1661 | "path": "Order", 1662 | "target": "Orders" 1663 | }, 1664 | { 1665 | "path": "Product", 1666 | "target": "Products" 1667 | } 1668 | ] 1669 | }, 1670 | { 1671 | "name": "Orders", 1672 | "entityType": "NorthwindModel.Order", 1673 | "navigationPropertyBinding": [ 1674 | { 1675 | "path": "Customer", 1676 | "target": "Customers" 1677 | }, 1678 | { 1679 | "path": "Employee", 1680 | "target": "Employees" 1681 | }, 1682 | { 1683 | "path": "Order_Details", 1684 | "target": "Order_Details" 1685 | }, 1686 | { 1687 | "path": "Shipper", 1688 | "target": "Shippers" 1689 | } 1690 | ] 1691 | }, 1692 | { 1693 | "name": "Products", 1694 | "entityType": "NorthwindModel.Product", 1695 | "navigationPropertyBinding": [ 1696 | { 1697 | "path": "Category", 1698 | "target": "Categories" 1699 | }, 1700 | { 1701 | "path": "Order_Details", 1702 | "target": "Order_Details" 1703 | }, 1704 | { 1705 | "path": "Supplier", 1706 | "target": "Suppliers" 1707 | } 1708 | ] 1709 | }, 1710 | { 1711 | "name": "Regions", 1712 | "entityType": "NorthwindModel.Region", 1713 | "navigationPropertyBinding": [ 1714 | { 1715 | "path": "Territories", 1716 | "target": "Territories" 1717 | } 1718 | ] 1719 | }, 1720 | { 1721 | "name": "Shippers", 1722 | "entityType": "NorthwindModel.Shipper", 1723 | "navigationPropertyBinding": [ 1724 | { 1725 | "path": "Orders", 1726 | "target": "Orders" 1727 | } 1728 | ] 1729 | }, 1730 | { 1731 | "name": "Suppliers", 1732 | "entityType": "NorthwindModel.Supplier", 1733 | "navigationPropertyBinding": [ 1734 | { 1735 | "path": "Products", 1736 | "target": "Products" 1737 | } 1738 | ] 1739 | }, 1740 | { 1741 | "name": "Territories", 1742 | "entityType": "NorthwindModel.Territory", 1743 | "navigationPropertyBinding": [ 1744 | { 1745 | "path": "Employees", 1746 | "target": "Employees" 1747 | }, 1748 | { 1749 | "path": "Region", 1750 | "target": "Regions" 1751 | } 1752 | ] 1753 | }, 1754 | { 1755 | "name": "Alphabetical_list_of_products", 1756 | "entityType": "NorthwindModel.Alphabetical_list_of_product" 1757 | }, 1758 | { 1759 | "name": "Category_Sales_for_1997", 1760 | "entityType": "NorthwindModel.Category_Sales_for_1997" 1761 | }, 1762 | { 1763 | "name": "Current_Product_Lists", 1764 | "entityType": "NorthwindModel.Current_Product_List" 1765 | }, 1766 | { 1767 | "name": "Customer_and_Suppliers_by_Cities", 1768 | "entityType": "NorthwindModel.Customer_and_Suppliers_by_City" 1769 | }, 1770 | { 1771 | "name": "Invoices", 1772 | "entityType": "NorthwindModel.Invoice" 1773 | }, 1774 | { 1775 | "name": "Order_Details_Extendeds", 1776 | "entityType": "NorthwindModel.Order_Details_Extended" 1777 | }, 1778 | { 1779 | "name": "Order_Subtotals", 1780 | "entityType": "NorthwindModel.Order_Subtotal" 1781 | }, 1782 | { 1783 | "name": "Orders_Qries", 1784 | "entityType": "NorthwindModel.Orders_Qry" 1785 | }, 1786 | { 1787 | "name": "Product_Sales_for_1997", 1788 | "entityType": "NorthwindModel.Product_Sales_for_1997" 1789 | }, 1790 | { 1791 | "name": "Products_Above_Average_Prices", 1792 | "entityType": "NorthwindModel.Products_Above_Average_Price" 1793 | }, 1794 | { 1795 | "name": "Products_by_Categories", 1796 | "entityType": "NorthwindModel.Products_by_Category" 1797 | }, 1798 | { 1799 | "name": "Sales_by_Categories", 1800 | "entityType": "NorthwindModel.Sales_by_Category" 1801 | }, 1802 | { 1803 | "name": "Sales_Totals_by_Amounts", 1804 | "entityType": "NorthwindModel.Sales_Totals_by_Amount" 1805 | }, 1806 | { 1807 | "name": "Summary_of_Sales_by_Quarters", 1808 | "entityType": "NorthwindModel.Summary_of_Sales_by_Quarter" 1809 | }, 1810 | { 1811 | "name": "Summary_of_Sales_by_Years", 1812 | "entityType": "NorthwindModel.Summary_of_Sales_by_Year" 1813 | } 1814 | ] 1815 | } 1816 | } 1817 | ] 1818 | } 1819 | } -------------------------------------------------------------------------------- /tests/schema2.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4.0", 3 | "dataServices": { 4 | "schema": [ 5 | { 6 | "namespace": "JayData.Test.CommonItems.Entities", 7 | "entityType": [ 8 | { 9 | "name": "User", 10 | "key": [ 11 | { 12 | "propertyRef": [ 13 | { 14 | "name": "Id" 15 | } 16 | ] 17 | } 18 | ], 19 | "property": [ 20 | { 21 | "name": "Id", 22 | "type": "Edm.Int32", 23 | "nullable": "false" 24 | }, 25 | { 26 | "name": "LoginName", 27 | "type": "Edm.String", 28 | "annotation": [ 29 | { 30 | "term": "UI.DisplayName" 31 | } 32 | ] 33 | }, 34 | { 35 | "name": "Email", 36 | "type": "Edm.String" 37 | }, 38 | { 39 | "name": "UserType", 40 | "type": "JayData.Test.CommonItems.Entities.UserType", 41 | "nullable": "false" 42 | } 43 | ], 44 | "navigationProperty": [ 45 | { 46 | "name": "Articles", 47 | "type": "Collection(JayData.Test.CommonItems.Entities.Article)" 48 | }, 49 | { 50 | "name": "Profile", 51 | "type": "JayData.Test.CommonItems.Entities.UserProfile" 52 | } 53 | ] 54 | }, 55 | { 56 | "name": "MyTClass", 57 | "abstract": "true", 58 | "openType": "true", 59 | "key": [ 60 | { 61 | "propertyRef": [ 62 | { 63 | "name": "Id" 64 | } 65 | ] 66 | } 67 | ], 68 | "property": [ 69 | { 70 | "name": "Id", 71 | "type": "Edm.Int32", 72 | "nullable": "false" 73 | }, 74 | { 75 | "name": "Title", 76 | "type": "Edm.String" 77 | } 78 | ] 79 | }, 80 | { 81 | "name": "Article", 82 | "baseType": "JayData.Test.CommonItems.Entities.MyTClass", 83 | "property": [ 84 | { 85 | "name": "RowVersion", 86 | "type": "Edm.Binary" 87 | }, 88 | { 89 | "name": "Lead", 90 | "type": "Edm.String" 91 | }, 92 | { 93 | "name": "Body", 94 | "type": "Edm.String" 95 | }, 96 | { 97 | "name": "CreateDate", 98 | "type": "Edm.DateTimeOffset" 99 | }, 100 | { 101 | "name": "Thumbnail_LowRes", 102 | "type": "Edm.Binary" 103 | }, 104 | { 105 | "name": "Thumbnail_HighRes", 106 | "type": "Edm.Binary" 107 | } 108 | ], 109 | "navigationProperty": [ 110 | { 111 | "name": "Category", 112 | "type": "JayData.Test.CommonItems.Entities.Category" 113 | }, 114 | { 115 | "name": "Tags", 116 | "type": "Collection(JayData.Test.CommonItems.Entities.TagConnection)" 117 | }, 118 | { 119 | "name": "Author", 120 | "type": "JayData.Test.CommonItems.Entities.User" 121 | }, 122 | { 123 | "name": "Reviewer", 124 | "type": "JayData.Test.CommonItems.Entities.User" 125 | } 126 | ] 127 | }, 128 | { 129 | "name": "UserProfile", 130 | "key": [ 131 | { 132 | "propertyRef": [ 133 | { 134 | "name": "Id" 135 | } 136 | ] 137 | } 138 | ], 139 | "property": [ 140 | { 141 | "name": "Id", 142 | "type": "Edm.Int32", 143 | "nullable": "false" 144 | }, 145 | { 146 | "name": "FullName", 147 | "type": "Edm.String" 148 | }, 149 | { 150 | "name": "Bio", 151 | "type": "Edm.String" 152 | }, 153 | { 154 | "name": "Avatar", 155 | "type": "Edm.Binary" 156 | }, 157 | { 158 | "name": "Birthday", 159 | "type": "Edm.DateTimeOffset" 160 | }, 161 | { 162 | "name": "Location", 163 | "type": "JayData.Test.CommonItems.Entities.Location" 164 | } 165 | ], 166 | "navigationProperty": [ 167 | { 168 | "name": "User", 169 | "type": "JayData.Test.CommonItems.Entities.User", 170 | "nullable": "false" 171 | } 172 | ] 173 | }, 174 | { 175 | "name": "Category", 176 | "baseType": "JayData.Test.CommonItems.Entities.MyTClass", 177 | "property": [ 178 | { 179 | "name": "RowVersion", 180 | "type": "Edm.Binary" 181 | }, 182 | { 183 | "name": "Subtitle", 184 | "type": "Edm.String" 185 | }, 186 | { 187 | "name": "Description", 188 | "type": "Edm.String" 189 | } 190 | ], 191 | "navigationProperty": [ 192 | { 193 | "name": "Articles", 194 | "type": "Collection(JayData.Test.CommonItems.Entities.Article)" 195 | } 196 | ] 197 | }, 198 | { 199 | "name": "Tag", 200 | "key": [ 201 | { 202 | "propertyRef": [ 203 | { 204 | "name": "Id" 205 | } 206 | ] 207 | } 208 | ], 209 | "property": [ 210 | { 211 | "name": "Id", 212 | "type": "Edm.Int32", 213 | "nullable": "false" 214 | }, 215 | { 216 | "name": "Title", 217 | "type": "Edm.String" 218 | } 219 | ], 220 | "navigationProperty": [ 221 | { 222 | "name": "Articles", 223 | "type": "Collection(JayData.Test.CommonItems.Entities.TagConnection)" 224 | } 225 | ] 226 | }, 227 | { 228 | "name": "TestItem", 229 | "key": [ 230 | { 231 | "propertyRef": [ 232 | { 233 | "name": "Id" 234 | } 235 | ] 236 | } 237 | ], 238 | "property": [ 239 | { 240 | "name": "Id", 241 | "type": "Edm.Int32", 242 | "nullable": "false" 243 | }, 244 | { 245 | "name": "i0", 246 | "type": "Edm.Int32" 247 | }, 248 | { 249 | "name": "b0", 250 | "type": "Edm.Boolean" 251 | }, 252 | { 253 | "name": "s0", 254 | "type": "Edm.String" 255 | }, 256 | { 257 | "name": "blob", 258 | "type": "Collection(Edm.Byte)" 259 | }, 260 | { 261 | "name": "n0", 262 | "type": "Edm.Double" 263 | }, 264 | { 265 | "name": "d0", 266 | "type": "Edm.DateTimeOffset" 267 | }, 268 | { 269 | "name": "g0", 270 | "type": "Edm.Guid" 271 | }, 272 | { 273 | "name": "l0", 274 | "type": "Edm.Int64" 275 | }, 276 | { 277 | "name": "de0", 278 | "type": "Edm.Decimal", 279 | "nullable": "false" 280 | }, 281 | { 282 | "name": "b1", 283 | "type": "Edm.Byte" 284 | } 285 | ], 286 | "navigationProperty": [ 287 | { 288 | "name": "Tags", 289 | "type": "Collection(JayData.Test.CommonItems.Entities.Tag)" 290 | }, 291 | { 292 | "name": "User", 293 | "type": "JayData.Test.CommonItems.Entities.User" 294 | } 295 | ] 296 | }, 297 | { 298 | "name": "TagConnection", 299 | "key": [ 300 | { 301 | "propertyRef": [ 302 | { 303 | "name": "Id" 304 | } 305 | ] 306 | } 307 | ], 308 | "property": [ 309 | { 310 | "name": "Id", 311 | "type": "Edm.Int32", 312 | "nullable": "false" 313 | } 314 | ], 315 | "navigationProperty": [ 316 | { 317 | "name": "Article", 318 | "type": "JayData.Test.CommonItems.Entities.Article" 319 | }, 320 | { 321 | "name": "Tag", 322 | "type": "JayData.Test.CommonItems.Entities.Tag" 323 | } 324 | ] 325 | }, 326 | { 327 | "name": "TestItemGuid", 328 | "openType": "true", 329 | "key": [ 330 | { 331 | "propertyRef": [ 332 | { 333 | "name": "Id" 334 | } 335 | ] 336 | } 337 | ], 338 | "property": [ 339 | { 340 | "name": "Id", 341 | "type": "Edm.Guid", 342 | "nullable": "false" 343 | }, 344 | { 345 | "name": "i0", 346 | "type": "Edm.Int32" 347 | }, 348 | { 349 | "name": "b0", 350 | "type": "Edm.Boolean" 351 | }, 352 | { 353 | "name": "s0", 354 | "type": "Edm.String" 355 | }, 356 | { 357 | "name": "time", 358 | "type": "Edm.TimeOfDay", 359 | "nullable": "false" 360 | }, 361 | { 362 | "name": "date", 363 | "type": "Edm.Date", 364 | "nullable": "false" 365 | }, 366 | { 367 | "name": "t", 368 | "type": "Edm.DateTimeOffset", 369 | "nullable": "false" 370 | }, 371 | { 372 | "name": "dur", 373 | "type": "Edm.Duration", 374 | "nullable": "false" 375 | }, 376 | { 377 | "name": "dtOffset", 378 | "type": "Edm.DateTimeOffset", 379 | "nullable": "false" 380 | }, 381 | { 382 | "name": "lng", 383 | "type": "Edm.Int64", 384 | "nullable": "false" 385 | }, 386 | { 387 | "name": "dec", 388 | "type": "Edm.Decimal", 389 | "nullable": "false" 390 | }, 391 | { 392 | "name": "flt", 393 | "type": "Edm.Single", 394 | "nullable": "false" 395 | }, 396 | { 397 | "name": "emails", 398 | "type": "Collection(Edm.String)" 399 | } 400 | ], 401 | "navigationProperty": [ 402 | { 403 | "name": "Group", 404 | "type": "JayData.Test.CommonItems.Entities.TestItemGroup" 405 | } 406 | ] 407 | }, 408 | { 409 | "name": "TestItemGroup", 410 | "key": [ 411 | { 412 | "propertyRef": [ 413 | { 414 | "name": "Id" 415 | } 416 | ] 417 | } 418 | ], 419 | "property": [ 420 | { 421 | "name": "Id", 422 | "type": "Edm.Guid", 423 | "nullable": "false" 424 | }, 425 | { 426 | "name": "Name", 427 | "type": "Edm.String" 428 | } 429 | ], 430 | "navigationProperty": [ 431 | { 432 | "name": "Items", 433 | "type": "Collection(JayData.Test.CommonItems.Entities.TestItemGuid)" 434 | } 435 | ] 436 | }, 437 | { 438 | "name": "TestItemType", 439 | "key": [ 440 | { 441 | "propertyRef": [ 442 | { 443 | "name": "Id" 444 | } 445 | ] 446 | } 447 | ], 448 | "property": [ 449 | { 450 | "name": "Id", 451 | "type": "Edm.Int32", 452 | "nullable": "false" 453 | }, 454 | { 455 | "name": "blob", 456 | "type": "Edm.Binary" 457 | }, 458 | { 459 | "name": "b0", 460 | "type": "Edm.Boolean" 461 | }, 462 | { 463 | "name": "b1", 464 | "type": "Edm.Byte" 465 | }, 466 | { 467 | "name": "d0", 468 | "type": "Edm.DateTimeOffset" 469 | }, 470 | { 471 | "name": "de0", 472 | "type": "Edm.Decimal", 473 | "nullable": "false" 474 | }, 475 | { 476 | "name": "n0", 477 | "type": "Edm.Double" 478 | }, 479 | { 480 | "name": "si0", 481 | "type": "Edm.Single" 482 | }, 483 | { 484 | "name": "g0", 485 | "type": "Edm.Guid" 486 | }, 487 | { 488 | "name": "i16", 489 | "type": "Edm.Int16" 490 | }, 491 | { 492 | "name": "i0", 493 | "type": "Edm.Int32" 494 | }, 495 | { 496 | "name": "i64", 497 | "type": "Edm.Int64" 498 | }, 499 | { 500 | "name": "s0", 501 | "type": "Edm.String" 502 | } 503 | ] 504 | } 505 | ], 506 | "complexType": [ 507 | { 508 | "name": "Location", 509 | "property": [ 510 | { 511 | "name": "Address", 512 | "type": "Edm.String" 513 | }, 514 | { 515 | "name": "City", 516 | "type": "Edm.String" 517 | }, 518 | { 519 | "name": "Zip", 520 | "type": "Edm.Int32", 521 | "nullable": "false" 522 | }, 523 | { 524 | "name": "Country", 525 | "type": "Edm.String" 526 | } 527 | ] 528 | } 529 | ], 530 | "enumType": [ 531 | { 532 | "name": "UserType", 533 | "member": [ 534 | { 535 | "name": "Admin", 536 | "value": "0" 537 | }, 538 | { 539 | "name": "Customer", 540 | "value": "1" 541 | }, 542 | { 543 | "name": "Guest", 544 | "value": "2" 545 | } 546 | ] 547 | } 548 | ], 549 | "annotations": [ 550 | { 551 | "target": "JayData.Test.CommonItems.Entities.User/Id", 552 | "annotation": [ 553 | { 554 | "term": "Org.OData.Core.V1.Computed", 555 | "bool": [ 556 | { 557 | "text": "true" 558 | } 559 | ] 560 | } 561 | ] 562 | }, 563 | { 564 | "target": "JayData.Test.CommonItems.Entities.Article/Id", 565 | "annotation": [ 566 | { 567 | "term": "Org.OData.Core.V1.Computed", 568 | "bool": "true" 569 | } 570 | ] 571 | }, 572 | { 573 | "target": "JayData.Test.CommonItems.Entities.Article/Lead", 574 | "annotation": [ 575 | { 576 | "term": "UI.DisplayName", 577 | "string": "Lead" 578 | } 579 | ] 580 | }, 581 | { 582 | "target": "JayData.Test.CommonItems.Entities.Article/Lead", 583 | "annotation": [ 584 | { 585 | "term": "UI.DisplayName", 586 | "string": [ 587 | { 588 | "text": "Lead" 589 | } 590 | ] 591 | } 592 | ] 593 | }, 594 | { 595 | "target": "JayData.Test.CommonItems.Entities.Category/Id", 596 | "annotation": [ 597 | { 598 | "term": "Org.OData.Core.V1.Computed", 599 | "bool": "true" 600 | }, 601 | { 602 | "term": "UI.DisplayName", 603 | "string": "Identifier" 604 | } 605 | ] 606 | } 607 | ] 608 | }, 609 | { 610 | "namespace": "Default", 611 | "action": [ 612 | { 613 | "name": "GetFirstArticleTitle", 614 | "isBound": "true", 615 | "parameter": [ 616 | { 617 | "name": "bindingParameter", 618 | "type": "JayData.Test.CommonItems.Entities.Category" 619 | }, 620 | { 621 | "name": "contains", 622 | "type": "Edm.String" 623 | } 624 | ], 625 | "returnType": { 626 | "type": "Edm.String" 627 | } 628 | }, 629 | { 630 | "name": "GetFirstArticleTitle", 631 | "isBound": "true", 632 | "parameter": [ 633 | { 634 | "name": "bindingParameter", 635 | "type": "Collection(JayData.Test.CommonItems.Entities.Category)" 636 | }, 637 | { 638 | "name": "contains", 639 | "type": "Edm.String" 640 | } 641 | ], 642 | "returnType": { 643 | "type": "Edm.String" 644 | } 645 | }, 646 | { 647 | "name": "SAction1", 648 | "parameter": [ 649 | { 650 | "name": "number1", 651 | "type": "Edm.Int32", 652 | "nullable": "false" 653 | } 654 | ], 655 | "returnType": { 656 | "type": "Edm.String" 657 | } 658 | }, 659 | { 660 | "name": "SAction2", 661 | "parameter": [ 662 | { 663 | "name": "count", 664 | "type": "Edm.Int32", 665 | "nullable": "false" 666 | } 667 | ], 668 | "returnType": { 669 | "type": "Collection(JayData.Test.CommonItems.Entities.Article)" 670 | } 671 | } 672 | ], 673 | "function": [ 674 | { 675 | "name": "LocationSwipe", 676 | "isBound": "true", 677 | "parameter": [ 678 | { 679 | "name": "bindingParameter", 680 | "type": "JayData.Test.CommonItems.Entities.Category" 681 | }, 682 | { 683 | "name": "Loc", 684 | "type": "Edm.GeographyPoint", 685 | "SRID": "Variable" 686 | } 687 | ], 688 | "returnType": { 689 | "type": "Edm.GeographyPoint", 690 | "SRID": "Variable" 691 | } 692 | }, 693 | { 694 | "name": "SFunction1", 695 | "parameter": [ 696 | { 697 | "name": "number2", 698 | "type": "Edm.Int32", 699 | "nullable": "false" 700 | } 701 | ], 702 | "returnType": { 703 | "type": "Collection(Edm.String)" 704 | } 705 | }, 706 | { 707 | "name": "SFunction2", 708 | "parameter": [ 709 | { 710 | "name": "number3", 711 | "type": "Edm.Int32", 712 | "nullable": "false" 713 | } 714 | ], 715 | "returnType": { 716 | "type": "Edm.String" 717 | } 718 | } 719 | ], 720 | "entityContainer": { 721 | "name": "Container", 722 | "entitySet": [ 723 | { 724 | "name": "Users", 725 | "entityType": "JayData.Test.CommonItems.Entities.User", 726 | "navigationPropertyBinding": [ 727 | { 728 | "path": "Articles", 729 | "target": "Articles" 730 | }, 731 | { 732 | "path": "Profile", 733 | "target": "UserProfiles" 734 | } 735 | ] 736 | }, 737 | { 738 | "name": "Articles", 739 | "entityType": "JayData.Test.CommonItems.Entities.Article", 740 | "navigationPropertyBinding": [ 741 | { 742 | "path": "Category", 743 | "target": "Categories" 744 | }, 745 | { 746 | "path": "Tags", 747 | "target": "TagConnections" 748 | }, 749 | { 750 | "path": "Author", 751 | "target": "Users" 752 | }, 753 | { 754 | "path": "Reviewer", 755 | "target": "Users" 756 | } 757 | ], 758 | "annotation": [ 759 | { 760 | "term": "Org.OData.Core.V1.OptimisticConcurrency", 761 | "collection": [ 762 | { 763 | "propertyPath": [ 764 | { 765 | "text": "RowVersion" 766 | } 767 | ] 768 | } 769 | ] 770 | } 771 | ] 772 | }, 773 | { 774 | "name": "UserProfiles", 775 | "entityType": "JayData.Test.CommonItems.Entities.UserProfile", 776 | "navigationPropertyBinding": [ 777 | { 778 | "path": "User", 779 | "target": "Users" 780 | } 781 | ] 782 | }, 783 | { 784 | "name": "Categories", 785 | "entityType": "JayData.Test.CommonItems.Entities.Category", 786 | "navigationPropertyBinding": [ 787 | { 788 | "path": "Articles", 789 | "target": "Articles" 790 | } 791 | ] 792 | }, 793 | { 794 | "name": "Tags", 795 | "entityType": "JayData.Test.CommonItems.Entities.Tag", 796 | "navigationPropertyBinding": [ 797 | { 798 | "path": "Articles", 799 | "target": "TagConnections" 800 | } 801 | ] 802 | }, 803 | { 804 | "name": "TestTable", 805 | "entityType": "JayData.Test.CommonItems.Entities.TestItem", 806 | "navigationPropertyBinding": [ 807 | { 808 | "path": "Tags", 809 | "target": "Tags" 810 | }, 811 | { 812 | "path": "User", 813 | "target": "Users" 814 | } 815 | ] 816 | }, 817 | { 818 | "name": "TagConnections", 819 | "entityType": "JayData.Test.CommonItems.Entities.TagConnection", 820 | "navigationPropertyBinding": [ 821 | { 822 | "path": "Article", 823 | "target": "Articles" 824 | }, 825 | { 826 | "path": "Tag", 827 | "target": "Tags" 828 | } 829 | ] 830 | }, 831 | { 832 | "name": "TestTable2", 833 | "entityType": "JayData.Test.CommonItems.Entities.TestItemGuid", 834 | "navigationPropertyBinding": [ 835 | { 836 | "path": "Group", 837 | "target": "TestItemGroups" 838 | } 839 | ] 840 | }, 841 | { 842 | "name": "TestItemGroups", 843 | "entityType": "JayData.Test.CommonItems.Entities.TestItemGroup", 844 | "navigationPropertyBinding": [ 845 | { 846 | "path": "Items", 847 | "target": "TestTable2" 848 | } 849 | ] 850 | }, 851 | { 852 | "name": "TestItemTypes", 853 | "entityType": "JayData.Test.CommonItems.Entities.TestItemType" 854 | } 855 | ], 856 | "actionImport": [ 857 | { 858 | "name": "SAction1", 859 | "action": "Default.SAction1" 860 | }, 861 | { 862 | "name": "SAction2", 863 | "action": "Default.SAction2", 864 | "entitySet": "Articles" 865 | } 866 | ], 867 | "functionImport": [ 868 | { 869 | "name": "SFunction1", 870 | "function": "Default.SFunction1", 871 | "includeInServiceDocument": "true" 872 | }, 873 | { 874 | "name": "SFunction2", 875 | "function": "Default.SFunction2" 876 | } 877 | ] 878 | } 879 | } 880 | ] 881 | } 882 | } -------------------------------------------------------------------------------- /tests/tses5-tests.js: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | var Edm = require('../lib/edm.js').Edm 4 | var expect = require('chai').expect 5 | 6 | describe("Edm.EntityProperty", () => { 7 | it("should support no init data", () => { 8 | var ep = new Edm.Property(); 9 | expect(ep).to.be.instanceof(Edm.Property) 10 | }); 11 | 12 | it("should support initialize name from init data", () => { 13 | var p = { 14 | name: "h", 15 | property: [ 16 | { name: "p1" }, { name: "p2" }, { name: "p3" } 17 | ] 18 | } 19 | var ed = new Edm.EntityType(p, {}) 20 | expect(ed.properties[0]).to.be.instanceof(Edm.Property) 21 | expect(ed.properties[0].name).to.equal("p1") 22 | }); 23 | }) 24 | 25 | describe("Edm.NavigationProperty", () => { 26 | 27 | 28 | it("should support initialize name from init data", () => { 29 | var p = { 30 | name: "h", 31 | referentialConstraint: [ 32 | { property: "p1" }, { property: "p2" }, { property: "p3" } 33 | ] 34 | } 35 | var ed = new Edm.NavigationProperty(p, {}) 36 | expect(ed.name).to.equal("h") 37 | expect(ed.referentialConstraints[0]).to.be.instanceof(Edm.ReferentialConstraint) 38 | expect(ed.referentialConstraints[0].property).to.equal("p1") 39 | }); 40 | }) 41 | 42 | describe("Edm.EntityType", () => { 43 | 44 | 45 | it("should support initialize name from init data", () => { 46 | var p = { 47 | name: "h", 48 | '@info': 'odata4-js incorrectly exports key as array, we follow this pattern in thests', 49 | key: [ 50 | { 51 | "propertyRef": [ 52 | { 53 | "name": "OrderID" 54 | }, 55 | { 56 | "name": "CustoerID" 57 | } 58 | ] 59 | } 60 | ], 61 | navigationProperty: [ 62 | { 63 | name: "np1", 64 | referentialConstraint: [ 65 | { property: "np1" }, { property: "p2" }, { property: "p3" } 66 | ] 67 | 68 | } 69 | ], 70 | property: [ 71 | { name: "p1" }, { name: "p2" }, { name: "p3" } 72 | ] 73 | } 74 | var ed = new Edm.EntityType(p, {}) 75 | expect(ed.name).to.equal("h") 76 | expect(ed.navigationProperties[0]).to.be.instanceof(Edm.NavigationProperty) 77 | expect(ed.properties[0]).to.be.instanceof(Edm.Property) 78 | expect(ed.navigationProperties[0].referentialConstraints[0].property).to.equal("np1") 79 | expect(ed.key).to.be.instanceof(Edm.Key) 80 | expect(ed.key.propertyRefs[0]).to.be.instanceof(Edm.PropertyRef) 81 | 82 | }); 83 | }) 84 | 85 | 86 | 87 | 88 | 89 | var nwindSchema = require('./schema.json') 90 | var entitySchema = nwindSchema.dataServices.schema[0] 91 | describe("Edm.Schema", () => { 92 | it("should support initialize name from init data", () => { 93 | var s = new Edm.Schema(entitySchema) 94 | //s. 95 | expect(s.entityTypes).to.have.length(26) 96 | expect(s.entityTypes[0]).to.be.instanceof(Edm.EntityType) 97 | expect(s.entityTypes[0].key.propertyRefs[0]).to.be.instanceof(Edm.PropertyRef) 98 | expect(s.entityTypes[0].key.propertyRefs[0].name).to.equal("CategoryID") 99 | }) 100 | }) 101 | 102 | var dataServices = nwindSchema.dataServices 103 | describe("Edm.DataService", () => { 104 | it("should support initialize name from init data (dataservice)", () => { 105 | var d = new Edm.DataServices(dataServices) 106 | var s = d.schemas[0] 107 | //s. 108 | expect(s.entityTypes).to.have.length(26) 109 | expect(s.entityTypes[0]).to.be.instanceof(Edm.EntityType) 110 | expect(s.entityTypes[0].key.propertyRefs[0]).to.be.instanceof(Edm.PropertyRef) 111 | expect(s.entityTypes[0].key.propertyRefs[0].name).to.equal("CategoryID") 112 | }) 113 | }) 114 | 115 | describe("Edm.Edmx", () => { 116 | it("should support initialize name from init data (edmx)", () => { 117 | var d = new Edm.Edmx(nwindSchema) 118 | var s = d.dataServices.schemas[0] 119 | //s. 120 | expect(s.entityTypes).to.have.length(26) 121 | expect(s.entityTypes[0]).to.be.instanceof(Edm.EntityType) 122 | expect(s.entityTypes[0].key.propertyRefs[0]).to.be.instanceof(Edm.PropertyRef) 123 | expect(s.entityTypes[0].key.propertyRefs[0].name).to.equal("CategoryID") 124 | }) 125 | }) 126 | 127 | describe("Edm.Reference", () => { 128 | it("should support initialize name from init data (edmx)", () => { 129 | var d = new Edm.Edmx(nwindSchema) 130 | 131 | expect(d.references).to.have.length(2) 132 | expect(d.references[0]).to.be.instanceof(Edm.Reference) 133 | expect(d.references[0].includes).to.have.length(1) 134 | expect(d.references[0].includes[0]).to.be.instanceof(Edm.ReferenceInclude) 135 | expect(d.references[0].includes[0].namespace).to.equal("Org.OData.Core.V1") 136 | expect(d.references[0].includes[0].alias).to.equal("Core") 137 | }) 138 | }) 139 | 140 | var o4schema = require('./schema2.json') 141 | 142 | describe("Edm.Action", () => { 143 | it("should support init data", () => { 144 | var json = o4schema.dataServices.schema[1] 145 | var schema = new Edm.Schema(json) 146 | var action = schema.actions[0] 147 | 148 | expect(action).to.be.instanceof(Edm.Action) 149 | expect(action.parameters).to.have.length(2) 150 | expect(action.parameters[0]).to.be.instanceof(Edm.Parameter) 151 | expect(action.parameters[0].name).to.be.equal("bindingParameter") 152 | }) 153 | }) 154 | 155 | describe("Edm.Action", () => { 156 | it("should support init data", () => { 157 | var json = o4schema.dataServices.schema[1] 158 | var schema = new Edm.Schema(json) 159 | var func = schema.functions[0] 160 | //console.log(schema.functions) 161 | 162 | expect(func).to.be.instanceof(Edm.Function) 163 | expect(func.parameters).to.have.length(2) 164 | expect(func.parameters[0]).to.be.instanceof(Edm.Parameter) 165 | expect(func.parameters[0].name).to.be.equal("bindingParameter") 166 | }) 167 | }) 168 | 169 | describe("Edm.ComplexType", () => { 170 | it("should support init data", () => { 171 | var json = o4schema.dataServices.schema[0] 172 | var schema = new Edm.Schema(json) 173 | 174 | expect(schema.complexTypes).to.have.length(1) 175 | expect(schema.complexTypes[0]).to.be.instanceof(Edm.ComplexType) 176 | expect(schema.complexTypes[0].properties[0]).to.be.instanceof(Edm.Property) 177 | expect(schema.complexTypes[0].properties[0].name).to.be.equal("Address") 178 | expect(schema.complexTypes[0].properties[0].type).to.equal(Edm.String.toString()) 179 | }) 180 | }) 181 | 182 | describe("Edm.EnumType", () => { 183 | it("should support init data", () => { 184 | var json = o4schema.dataServices.schema[0] 185 | var schema = new Edm.Schema(json) 186 | 187 | expect(schema.enumTypes).to.have.length(1) 188 | expect(schema.enumTypes[0]).to.be.instanceof(Edm.EnumType) 189 | expect(schema.enumTypes[0].members).to.have.length(3) 190 | expect(schema.enumTypes[0].members[0]).to.instanceof(Edm.Member) 191 | expect(schema.enumTypes[0].members[0].name).to.equal("Admin") 192 | expect(schema.enumTypes[0].members[0].value).to.equal('0') 193 | }) 194 | }) 195 | 196 | describe("Edm.Annotations", () => { 197 | var attributeCount = 5; 198 | 199 | it("Edm.BoolAnnotation attribute", () => { 200 | var json = o4schema.dataServices.schema[0] 201 | var schema = new Edm.Schema(json) 202 | 203 | expect(schema.annotations).to.have.length(attributeCount) 204 | expect(schema.annotations[0]).to.be.instanceof(Edm.Annotations) 205 | expect(schema.annotations[0].annotations).to.have.length(1) 206 | expect(schema.annotations[0].annotations[0]).to.instanceof(Edm.BoolAnnotation) 207 | expect(schema.annotations[0].annotations[0].term).to.equal("Org.OData.Core.V1.Computed") 208 | expect(schema.annotations[0].annotations[0].bool).to.equal("true") 209 | }) 210 | 211 | it("Edm.BoolAnnotation child", () => { 212 | var json = o4schema.dataServices.schema[0] 213 | var schema = new Edm.Schema(json) 214 | 215 | expect(schema.annotations).to.have.length(attributeCount) 216 | expect(schema.annotations[1]).to.be.instanceof(Edm.Annotations) 217 | expect(schema.annotations[1].annotations).to.have.length(1) 218 | expect(schema.annotations[1].annotations[0]).to.instanceof(Edm.BoolAnnotation) 219 | expect(schema.annotations[1].annotations[0].term).to.equal("Org.OData.Core.V1.Computed") 220 | expect(schema.annotations[1].annotations[0].bool).to.equal("true") 221 | }) 222 | it("Edm.StringAnnotation attribute", () => { 223 | var json = o4schema.dataServices.schema[0] 224 | var schema = new Edm.Schema(json) 225 | 226 | expect(schema.annotations).to.have.length(attributeCount) 227 | expect(schema.annotations[2]).to.be.instanceof(Edm.Annotations) 228 | expect(schema.annotations[2].annotations).to.have.length(1) 229 | expect(schema.annotations[2].annotations[0]).to.instanceof(Edm.StringAnnotation) 230 | expect(schema.annotations[2].annotations[0].term).to.equal("UI.DisplayName") 231 | expect(schema.annotations[2].annotations[0].string).to.equal("Lead") 232 | }) 233 | 234 | it("Edm.StringAnnotation child", () => { 235 | var json = o4schema.dataServices.schema[0] 236 | var schema = new Edm.Schema(json) 237 | 238 | expect(schema.annotations).to.have.length(attributeCount) 239 | expect(schema.annotations[3]).to.be.instanceof(Edm.Annotations) 240 | expect(schema.annotations[3].annotations).to.have.length(1) 241 | expect(schema.annotations[3].annotations[0]).to.instanceof(Edm.StringAnnotation) 242 | expect(schema.annotations[3].annotations[0].term).to.equal("UI.DisplayName") 243 | expect(schema.annotations[3].annotations[0].string).to.equal("Lead") 244 | }) 245 | 246 | it("Multiple annotations", () => { 247 | var json = o4schema.dataServices.schema[0] 248 | var schema = new Edm.Schema(json) 249 | 250 | expect(schema.annotations).to.have.length(attributeCount) 251 | expect(schema.annotations[4]).to.be.instanceof(Edm.Annotations) 252 | expect(schema.annotations[4].annotations).to.have.length(2) 253 | 254 | expect(schema.annotations[4].annotations[0]).to.instanceof(Edm.BoolAnnotation) 255 | expect(schema.annotations[4].annotations[0].term).to.equal("Org.OData.Core.V1.Computed") 256 | expect(schema.annotations[4].annotations[0].bool).to.equal("true") 257 | 258 | expect(schema.annotations[4].annotations[1]).to.instanceof(Edm.StringAnnotation) 259 | expect(schema.annotations[4].annotations[1].term).to.equal("UI.DisplayName") 260 | expect(schema.annotations[4].annotations[1].string).to.equal("Identifier") 261 | }) 262 | 263 | it("Edm.Annotation on property", () => { 264 | var p = { 265 | name: "h", 266 | property: [ 267 | { name: "p1" }, 268 | { name: "p2" }, 269 | { 270 | name: "p3", 271 | annotation: [ 272 | { 273 | term: "UI.DisplayName" 274 | } 275 | ] 276 | } 277 | ] 278 | } 279 | var ed = new Edm.EntityType(p, {}) 280 | expect(ed.properties[2]).to.be.instanceof(Edm.Property) 281 | expect(ed.properties[2].name).to.equal("p3") 282 | expect(ed.properties[2].annotations[0]).to.be.instanceof(Edm.Annotation) 283 | expect(ed.properties[2].annotations[0].term).to.equal("UI.DisplayName") 284 | }) 285 | 286 | it("Edm.Annotation on navigationProperty", () => { 287 | var p = { 288 | name: "h", 289 | navigationProperty: [ 290 | { name: "p1" }, 291 | { name: "p2" }, 292 | { 293 | name: "p3", 294 | annotation: [ 295 | { 296 | term: "UI.DisplayName" 297 | } 298 | ] 299 | } 300 | ] 301 | } 302 | var ed = new Edm.EntityType(p, {}) 303 | expect(ed.navigationProperties[2]).to.be.instanceof(Edm.NavigationProperty) 304 | expect(ed.navigationProperties[2].name).to.equal("p3") 305 | expect(ed.navigationProperties[2].annotations[0]).to.be.instanceof(Edm.Annotation) 306 | expect(ed.navigationProperties[2].annotations[0].term).to.equal("UI.DisplayName") 307 | }) 308 | 309 | it("Edm.Annotation on type", () => { 310 | var p = { 311 | name: "h", 312 | property: [ 313 | { name: "p1" }, 314 | { name: "p2" }, 315 | { name: "p3" } 316 | ], 317 | annotation: [ 318 | { 319 | term: "UI.DisplayName", 320 | string: 'hh' 321 | } 322 | ] 323 | } 324 | var ed = new Edm.EntityType(p, {}) 325 | expect(ed.properties[2]).to.be.instanceof(Edm.Property) 326 | expect(ed.properties[2].name).to.equal("p3") 327 | expect(ed.annotations[0]).to.be.instanceof(Edm.StringAnnotation) 328 | expect(ed.annotations[0].term).to.equal("UI.DisplayName") 329 | expect(ed.annotations[0].string).to.equal("hh") 330 | }) 331 | 332 | it("Edm.Annotation on complex type", () => { 333 | var p = { 334 | name: "h", 335 | property: [ 336 | { name: "p1" }, 337 | { name: "p2" }, 338 | { name: "p3" } 339 | ], 340 | annotation: [ 341 | { 342 | term: "UI.DisplayName", 343 | string: 'hh' 344 | } 345 | ] 346 | } 347 | var ed = new Edm.ComplexType(p, {}) 348 | expect(ed.properties[2]).to.be.instanceof(Edm.Property) 349 | expect(ed.properties[2].name).to.equal("p3") 350 | expect(ed.annotations[0]).to.be.instanceof(Edm.StringAnnotation) 351 | expect(ed.annotations[0].term).to.equal("UI.DisplayName") 352 | expect(ed.annotations[0].string).to.equal("hh") 353 | }) 354 | 355 | it("Edm.Annotation on type for property", () => { 356 | var p = { 357 | name: "h", 358 | property: [ 359 | { name: "p1" }, 360 | { name: "p2" }, 361 | { name: "p3" } 362 | ], 363 | annotation: [ 364 | { 365 | term: "UI.DisplayName", 366 | string: 'hh', 367 | path: 'p3' 368 | } 369 | ] 370 | } 371 | var ed = new Edm.EntityType(p, {}) 372 | expect(ed.properties[2]).to.be.instanceof(Edm.Property) 373 | expect(ed.properties[2].name).to.equal("p3") 374 | expect(ed.annotations[0]).to.be.instanceof(Edm.StringAnnotation) 375 | expect(ed.annotations[0].term).to.equal("UI.DisplayName") 376 | expect(ed.annotations[0].string).to.equal("hh") 377 | expect(ed.annotations[0].path).to.equal("p3") 378 | }) 379 | 380 | it("Edm.Annotation on action parameter", () => { 381 | var p = { 382 | name: "h", 383 | parameter: [ 384 | { name: "p1", type: "Edm.String" }, 385 | { name: "p2", type: "Edm.Int32" }, 386 | { 387 | name: "p3", 388 | type: "Edm.String", 389 | annotation: [ 390 | { 391 | term: "UI.ControlHint", 392 | string: 'hh' 393 | } 394 | ] 395 | } 396 | ] 397 | } 398 | var ed = new Edm.Action(p, {}) 399 | expect(ed.parameters[2]).to.be.instanceof(Edm.Parameter) 400 | expect(ed.parameters[2].name).to.equal("p3") 401 | expect(ed.parameters[2].annotations[0]).to.be.instanceof(Edm.StringAnnotation) 402 | expect(ed.parameters[2].annotations[0].term).to.equal("UI.ControlHint") 403 | expect(ed.parameters[2].annotations[0].string).to.equal("hh") 404 | }) 405 | 406 | it("Edm.Annotation on action returnType", () => { 407 | var p = { 408 | name: "h", 409 | parameter: [ 410 | { name: "p1", type: "Edm.String" }, 411 | { name: "p2", type: "Edm.Int32" }, 412 | { name: "p3", type: "Edm.String" } 413 | ], 414 | returnType: { 415 | type: "Edm.String", 416 | annotation: [ 417 | { 418 | term: "UI.ControlHint", 419 | string: 'hh' 420 | } 421 | ] 422 | } 423 | } 424 | var ed = new Edm.Action(p, {}) 425 | expect(ed.returnType).to.be.instanceof(Edm.ReturnType) 426 | expect(ed.returnType.type).to.equal("Edm.String") 427 | expect(ed.returnType.annotations[0]).to.be.instanceof(Edm.StringAnnotation) 428 | expect(ed.returnType.annotations[0].term).to.equal("UI.ControlHint") 429 | expect(ed.returnType.annotations[0].string).to.equal("hh") 430 | }) 431 | 432 | it("Edm.Annotation on action", () => { 433 | var p = { 434 | name: "h", 435 | parameter: [ 436 | { name: "p1", type: "Edm.String" }, 437 | { name: "p2", type: "Edm.Int32" }, 438 | { name: "p3", type: "Edm.String" } 439 | ], 440 | annotation: [ 441 | { 442 | term: "UI.ControlHint", 443 | string: 'hh', 444 | path: 'p3' 445 | } 446 | ] 447 | } 448 | var ed = new Edm.Action(p, {}) 449 | expect(ed.parameters[2]).to.be.instanceof(Edm.Parameter) 450 | expect(ed.parameters[2].name).to.equal("p3") 451 | expect(ed.annotations[0]).to.be.instanceof(Edm.StringAnnotation) 452 | expect(ed.annotations[0].term).to.equal("UI.ControlHint") 453 | expect(ed.annotations[0].string).to.equal("hh") 454 | expect(ed.annotations[0].path).to.equal("p3") 455 | }) 456 | 457 | it("Edm.Annotation on function parameter", () => { 458 | var p = { 459 | name: "h", 460 | parameter: [ 461 | { name: "p1", type: "Edm.String" }, 462 | { name: "p2", type: "Edm.Int32" }, 463 | { 464 | name: "p3", 465 | type: "Edm.String", 466 | annotation: [ 467 | { 468 | term: "UI.ControlHint", 469 | string: 'hh' 470 | } 471 | ] 472 | } 473 | ] 474 | } 475 | var ed = new Edm.Function(p, {}) 476 | expect(ed.parameters[2]).to.be.instanceof(Edm.Parameter) 477 | expect(ed.parameters[2].name).to.equal("p3") 478 | expect(ed.parameters[2].annotations[0]).to.be.instanceof(Edm.StringAnnotation) 479 | expect(ed.parameters[2].annotations[0].term).to.equal("UI.ControlHint") 480 | expect(ed.parameters[2].annotations[0].string).to.equal("hh") 481 | }) 482 | 483 | it("Edm.Annotation on function returnType", () => { 484 | var p = { 485 | name: "h", 486 | parameter: [ 487 | { name: "p1", type: "Edm.String" }, 488 | { name: "p2", type: "Edm.Int32" }, 489 | { name: "p3", type: "Edm.String" } 490 | ], 491 | returnType: { 492 | type: "Edm.String", 493 | annotation: [ 494 | { 495 | term: "UI.ControlHint", 496 | string: 'hh' 497 | } 498 | ] 499 | } 500 | } 501 | var ed = new Edm.Function(p, {}) 502 | expect(ed.returnType).to.be.instanceof(Edm.ReturnType) 503 | expect(ed.returnType.type).to.equal("Edm.String") 504 | expect(ed.returnType.annotations[0]).to.be.instanceof(Edm.StringAnnotation) 505 | expect(ed.returnType.annotations[0].term).to.equal("UI.ControlHint") 506 | expect(ed.returnType.annotations[0].string).to.equal("hh") 507 | }) 508 | 509 | it("Edm.Annotation on function", () => { 510 | var p = { 511 | name: "h", 512 | parameter: [ 513 | { name: "p1", type: "Edm.String" }, 514 | { name: "p2", type: "Edm.Int32" }, 515 | { name: "p3", type: "Edm.String" } 516 | ], 517 | annotation: [ 518 | { 519 | term: "UI.ControlHint", 520 | string: 'hh', 521 | path: 'p3' 522 | } 523 | ] 524 | } 525 | var ed = new Edm.Function(p, {}) 526 | expect(ed.parameters[2]).to.be.instanceof(Edm.Parameter) 527 | expect(ed.parameters[2].name).to.equal("p3") 528 | expect(ed.annotations[0]).to.be.instanceof(Edm.StringAnnotation) 529 | expect(ed.annotations[0].term).to.equal("UI.ControlHint") 530 | expect(ed.annotations[0].string).to.equal("hh") 531 | expect(ed.annotations[0].path).to.equal("p3") 532 | }) 533 | 534 | it("Edm.Annotation on EnumType", () => { 535 | var p = { 536 | "name": "UserType", 537 | "member": [ 538 | { 539 | "name": "Admin", 540 | "value": "0" 541 | }, 542 | { 543 | "name": "Customer", 544 | "value": "1" 545 | }, 546 | { 547 | "name": "Guest", 548 | "value": "2" 549 | } 550 | ], 551 | annotation: [ 552 | { 553 | term: "UI.ControlHint", 554 | string: 'hh', 555 | path: 'Guest' 556 | } 557 | ] 558 | } 559 | var ed = new Edm.EnumType(p, {}) 560 | expect(ed.members[2]).to.be.instanceof(Edm.Member) 561 | expect(ed.members[2].name).to.equal("Guest") 562 | expect(ed.annotations[0]).to.be.instanceof(Edm.StringAnnotation) 563 | expect(ed.annotations[0].term).to.equal("UI.ControlHint") 564 | expect(ed.annotations[0].string).to.equal("hh") 565 | expect(ed.annotations[0].path).to.equal("Guest") 566 | }) 567 | 568 | it("Edm.Annotation on EnumType member", () => { 569 | var p = { 570 | "name": "UserType", 571 | "member": [ 572 | { 573 | "name": "Admin", 574 | "value": "0" 575 | }, 576 | { 577 | "name": "Customer", 578 | "value": "1" 579 | }, 580 | { 581 | "name": "Guest", 582 | "value": "2", 583 | "annotation": [ 584 | { 585 | term: "UI.ControlHint", 586 | string: 'hh' 587 | } 588 | ] 589 | } 590 | ] 591 | } 592 | var ed = new Edm.EnumType(p, {}) 593 | expect(ed.members[2]).to.be.instanceof(Edm.Member) 594 | expect(ed.members[2].name).to.equal("Guest") 595 | expect(ed.members[2].annotations[0]).to.be.instanceof(Edm.StringAnnotation) 596 | expect(ed.members[2].annotations[0].term).to.equal("UI.ControlHint") 597 | expect(ed.members[2].annotations[0].string).to.equal("hh") 598 | }) 599 | 600 | it("Edm.Annotation on EntitySet", () => { 601 | var p = { 602 | "name": "Articles", 603 | "entityType": "JayData.Test.CommonItems.Entities.Article", 604 | "navigationPropertyBinding": [ 605 | { 606 | "path": "Category", 607 | "target": "Categories" 608 | }, 609 | { 610 | "path": "Tags", 611 | "target": "TagConnections" 612 | }, 613 | { 614 | "path": "Author", 615 | "target": "Users" 616 | }, 617 | { 618 | "path": "Reviewer", 619 | "target": "Users" 620 | } 621 | ], 622 | "annotation": [ 623 | { 624 | "term": "Org.OData.Core.V1.OptimisticConcurrency", 625 | "collection": [ 626 | { 627 | "propertyPath": [ 628 | { 629 | "text": "RowVersion" 630 | } 631 | ] 632 | } 633 | ] 634 | } 635 | ] 636 | } 637 | var ed = new Edm.EntitySet(p, {}) 638 | expect(ed.annotations[0]).to.be.instanceof(Edm.PropertyPathAnnotation) 639 | expect(ed.annotations[0].term).to.equal("Org.OData.Core.V1.OptimisticConcurrency") 640 | expect(ed.annotations[0].propertyPaths).to.deep.equal(["RowVersion"]) 641 | }) 642 | 643 | it("Edm.StringAnnotation collection value", () => { 644 | var p = { 645 | "term": "org.example.seo.SeoTerms", 646 | "collection": [ 647 | { 648 | "string": [ 649 | { 650 | "text": "Product" 651 | }, 652 | { 653 | "text": "Supplier" 654 | }, 655 | { 656 | "text": "Customer" 657 | } 658 | ] 659 | } 660 | ] 661 | } 662 | var ed = new Edm.StringAnnotation(p, {}) 663 | 664 | expect(ed).to.be.instanceof(Edm.StringAnnotation) 665 | expect(ed.term).to.equal("org.example.seo.SeoTerms") 666 | expect(ed.string).to.deep.equal(["Product", "Supplier", "Customer"]) 667 | 668 | }) 669 | 670 | it("Edm.NullAnnotation", () => { 671 | var p = { 672 | "name": "Description", 673 | "type": "Edm.String", 674 | "annotation": [ 675 | { 676 | "term": "org.example.display.DisplayName", 677 | "null": [ 678 | {} 679 | ] 680 | } 681 | ] 682 | } 683 | var ed = new Edm.Property(p, {}) 684 | expect(ed.annotations[0]).to.be.instanceof(Edm.NullAnnotation) 685 | expect(ed.annotations[0].term).to.equal("org.example.display.DisplayName") 686 | expect(ed.annotations[0].null).to.be.undefined 687 | }) 688 | }) 689 | 690 | 691 | 692 | 693 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "experimentalDecorators": true, 4 | "outDir": "lib", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "emitDecoratorMetadata": true, 8 | "declaration": true, 9 | "watch": false, 10 | "sourceMap": true 11 | }, 12 | "exclude": [ 13 | "node_modules", 14 | "lib" 15 | ] 16 | } --------------------------------------------------------------------------------