query-core 0.1.5 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,28 +3,28 @@ import {Attribute, Attributes, Statement, StringMap} from './metadata';
3
3
  import {buildDollarParam, buildMsSQLParam, buildOracleParam, buildQuery, buildSort as bs, LikeType} from './query';
4
4
  import {buildFromQuery, oracle, SearchResult} from './search';
5
5
 
6
- export const postgre = 'postgre';
6
+ export const postgres = 'postgres';
7
7
  export const mssql = 'mssql';
8
8
  export const mysql = 'mysql';
9
9
  export const sqlite = 'sqlite';
10
10
  export class SearchBuilder<T, S> {
11
11
  map?: StringMap;
12
12
  bools?: Attribute[];
13
- buildQuery: (s: S, bparam: LikeType|((i: number ) => string), table?: string, attrs?: Attributes, sort?: string, fields?: string[], sq?: string, strExcluding?: string, buildSort3?: (sort: string, map?: Attributes|StringMap) => string) => Statement;
13
+ buildQuery: (s: S, bparam: LikeType|((i: number ) => string), table?: string, attrs?: Attributes, sort?: string, fields?: string[], sq?: string, strExcluding?: string, buildSort3?: (sort?: string, map?: Attributes|StringMap) => string) => Statement|undefined;
14
14
  q?: string;
15
15
  excluding?: string;
16
- buildSort?: (sort: string, map?: Attributes|StringMap) => string;
17
- buildParam?: (i: number) => string;
16
+ buildSort?: (sort?: string, map?: Attributes|StringMap) => string;
17
+ buildParam: (i: number) => string;
18
18
  total?: string;
19
19
  constructor(public query: (sql: string, args?: any[], m?: StringMap, bools?: Attribute[]) => Promise<T[]>, public table: string,
20
20
  public attributes?: Attributes,
21
21
  public provider?: string,
22
- buildQ?: (s: S, bparam: LikeType|((i: number ) => string), table?: string, attrs?: Attributes, sort?: string, fields?: string[], sq?: string, strExcluding?: string, buildSort3?: (sort: string, map?: Attributes|StringMap) => string) => Statement,
22
+ buildQ?: (s: S, bparam: LikeType|((i: number ) => string), table?: string, attrs?: Attributes, sort?: string, fields?: string[], sq?: string, strExcluding?: string, buildSort3?: (sort?: string, map?: Attributes|StringMap) => string) => Statement|undefined,
23
23
  public fromDB?: (v: T) => T,
24
24
  public sort?: string,
25
25
  q?: string,
26
26
  excluding?: string,
27
- buildSort?: (sort: string, map?: Attributes|StringMap) => string,
27
+ buildSort?: (sort?: string, map?: Attributes|StringMap) => string,
28
28
  buildParam?: (i: number) => string,
29
29
  total?: string) {
30
30
  if (attributes) {
@@ -43,7 +43,7 @@ export class SearchBuilder<T, S> {
43
43
  } else {
44
44
  if (provider === oracle) {
45
45
  this.buildParam = buildOracleParam;
46
- } else if (provider === postgre) {
46
+ } else if (provider === postgres) {
47
47
  this.buildParam = buildDollarParam;
48
48
  } else if (provider === mssql) {
49
49
  this.buildParam = buildMsSQLParam;
@@ -53,16 +53,25 @@ export class SearchBuilder<T, S> {
53
53
  }
54
54
  this.total = (total && total.length > 0 ? total : 'total');
55
55
  }
56
- search(s: S, limit?: number, skip?: number, fields?: string[]): Promise<SearchResult<T>> {
56
+ search(s: S, limit?: number, offset?: number|string, fields?: string[]): Promise<SearchResult<T>> {
57
+ let skip = 0;
58
+ if (typeof offset === 'number' && offset > 0) {
59
+ skip = offset;
60
+ }
57
61
  const st = (this.sort ? this.sort : 'sort');
58
- const sn = s[st] as string;
59
- delete s[st];
60
- const x = (this.provider === postgre ? 'ilike' : this.buildParam);
61
- const q2 = buildQuery(s, x, this.table, this.attributes, sn, fields, this.q, this.excluding, this.buildSort);
62
- if (this.fromDB) {
62
+ const sn = (s as any)[st] as string;
63
+ delete (s as any)[st];
64
+ const x = (this.provider === postgres ? 'ilike' : this.buildParam);
65
+ const q2 = this.buildQuery(s, x, this.table, this.attributes, sn, fields, this.q, this.excluding, this.buildSort);
66
+ if (!q2) {
67
+ throw new Error('Cannot build query');
68
+ }
69
+ const fn = this.fromDB;
70
+ if (fn) {
63
71
  return buildFromQuery(this.query, q2.query, q2.params, limit, skip, this.map, this.bools, this.provider, this.total).then(r => {
64
72
  if (r.list && r.list.length > 0) {
65
- r.list = r.list.map(o => this.fromDB(o));
73
+ r.list = r.list.map(o => fn(o));
74
+ return r;
66
75
  } else {
67
76
  return r;
68
77
  }
package/src/batch.ts CHANGED
@@ -53,7 +53,7 @@ export class SqlUpdater<T> {
53
53
  }
54
54
  export class SqlBatchInserter<T> {
55
55
  version?: string;
56
- constructor(public exec: (sql: string, args?: any[]) => Promise<number>, public table: string, public attributes: Attributes, public param: (i: number) => string, public map?: (v: T) => T) {
56
+ constructor(public exec: (sql: string, args?: any[]) => Promise<number>, public table: string, public attributes: Attributes, public param: ((i: number) => string)|boolean, public map?: (v: T) => T) {
57
57
  this.write = this.write.bind(this);
58
58
  const x = version(attributes);
59
59
  if (x) {
@@ -72,7 +72,7 @@ export class SqlBatchInserter<T> {
72
72
  list.push(obj2);
73
73
  }
74
74
  }
75
- const stmt = buildToInsertBatch(list, this.table, this.attributes, this.param);
75
+ const stmt = buildToInsertBatch(list, this.table, this.attributes, this.param, this.version);
76
76
  if (stmt) {
77
77
  return this.exec(stmt.query, stmt.params);
78
78
  } else {
package/src/build.ts CHANGED
@@ -1,6 +1,16 @@
1
1
  import {Attribute, Attributes, Statement, StringMap} from './metadata';
2
2
 
3
- export function select<T>(obj: T, table: string, ks: Attribute[], buildParam: (i: number) => string, i?: number): Statement {
3
+ export function params(length: number, p: (i: number) => string, from?: number): string[] {
4
+ if (from === undefined || from == null) {
5
+ from = 0;
6
+ }
7
+ const ps: string[] = [];
8
+ for (let i = 1; i <= length; i++) {
9
+ ps.push(p(i + from));
10
+ }
11
+ return ps;
12
+ }
13
+ export function select<T>(obj: T, table: string, ks: Attribute[], buildParam: (i: number) => string, i?: number): Statement|undefined {
4
14
  if (!i) {
5
15
  i = 1;
6
16
  }
@@ -17,17 +27,19 @@ export function select<T>(obj: T, table: string, ks: Attribute[], buildParam: (i
17
27
  const cols: string[] = [];
18
28
  const args: any[] = [];
19
29
  for (const k of ks) {
20
- const field = (k.field ? k.field : k.name);
21
- cols.push(`${field} = ${buildParam(i++)}`);
22
- args.push(obj[k.name]);
30
+ if (k.name) {
31
+ const field = (k.field ? k.field : k.name);
32
+ cols.push(`${field} = ${buildParam(i++)}`);
33
+ args.push((obj as any)[k.name]);
34
+ }
23
35
  }
24
36
  const query = `select * from ${table} where ${cols.join(' and ')}`;
25
37
  return { query, params: args };
26
38
  } else {
27
- return null;
39
+ return undefined;
28
40
  }
29
41
  }
30
- export function exist<T>(obj: T, table: string, ks: Attribute[], buildParam: (i: number) => string, col?: string, i?: number): Statement {
42
+ export function exist<T>(obj: T, table: string, ks: Attribute[], buildParam: (i: number) => string, col?: string, i?: number): Statement|undefined {
31
43
  if (!i) {
32
44
  i = 1;
33
45
  }
@@ -47,17 +59,19 @@ export function exist<T>(obj: T, table: string, ks: Attribute[], buildParam: (i:
47
59
  const cols: string[] = [];
48
60
  const args: any[] = [];
49
61
  for (const k of ks) {
50
- const field = (k.field ? k.field : k.name);
51
- cols.push(`${field} = ${buildParam(i++)}`);
52
- args.push(obj[k.name]);
62
+ if (k.name) {
63
+ const field = (k.field ? k.field : k.name);
64
+ cols.push(`${field} = ${buildParam(i++)}`);
65
+ args.push((obj as any)[k.name]);
66
+ }
53
67
  }
54
68
  const query = `select * from ${table} where ${cols.join(' and ')}`;
55
69
  return { query, params: args };
56
70
  } else {
57
- return null;
71
+ return undefined;
58
72
  }
59
73
  }
60
- export function buildToDelete<T>(obj: T, table: string, ks: Attribute[], buildParam: (i: number) => string, i?: number): Statement {
74
+ export function buildToDelete<T>(obj: T, table: string, ks: Attribute[], buildParam: (i: number) => string, i?: number): Statement|undefined {
61
75
  if (!i) {
62
76
  i = 1;
63
77
  }
@@ -74,14 +88,16 @@ export function buildToDelete<T>(obj: T, table: string, ks: Attribute[], buildPa
74
88
  const cols: string[] = [];
75
89
  const args: any[] = [];
76
90
  for (const k of ks) {
77
- const field = (k.field ? k.field : k.name);
78
- cols.push(`${field} = ${buildParam(i++)}`);
79
- args.push(obj[k.name]);
91
+ if (k.name) {
92
+ const field = (k.field ? k.field : k.name);
93
+ cols.push(`${field} = ${buildParam(i++)}`);
94
+ args.push((obj as any)[k.name]);
95
+ }
80
96
  }
81
97
  const query = `delete from ${table} where ${cols.join(' and ')}`;
82
98
  return { query, params: args };
83
99
  } else {
84
- return null;
100
+ return undefined;
85
101
  }
86
102
  }
87
103
  export function insert<T>(exec: (sql: string, args?: any[]) => Promise<number>, obj: T, table: string, attrs: Attributes, buildParam: (i: number) => string, ver?: string, i?: number): Promise<number> {
@@ -92,17 +108,18 @@ export function insert<T>(exec: (sql: string, args?: any[]) => Promise<number>,
92
108
  return exec(stm.query, stm.params);
93
109
  }
94
110
  }
95
- export function buildToInsert<T>(obj: T, table: string, attrs: Attributes, buildParam: (i: number) => string, ver?: string, i?: number): Statement {
111
+ export function buildToInsert<T>(obj: T, table: string, attrs: Attributes, buildParam: (i: number) => string, ver?: string, i?: number): Statement|undefined {
96
112
  if (!i) {
97
113
  i = 1;
98
114
  }
115
+ const o: any = obj;
99
116
  const ks = Object.keys(attrs);
100
117
  const cols: string[] = [];
101
118
  const values: string[] = [];
102
119
  const args: any[] = [];
103
120
  let isVersion = false;
104
121
  for (const k of ks) {
105
- let v = obj[k];
122
+ let v = o[k];
106
123
  const attr = attrs[k];
107
124
  if (attr && !attr.ignored && !attr.noinsert) {
108
125
  if (v === undefined || v == null) {
@@ -153,82 +170,162 @@ export function buildToInsert<T>(obj: T, table: string, attrs: Attributes, build
153
170
  values.push(`${1}`);
154
171
  }
155
172
  if (cols.length === 0) {
156
- return null;
173
+ return undefined;
157
174
  } else {
158
175
  const query = `insert into ${table}(${cols.join(',')})values(${values.join(',')})`;
159
176
  return { query, params: args };
160
177
  }
161
178
  }
162
- export function insertBatch<T>(exec: (sql: string, args?: any[]) => Promise<number>, objs: T[], table: string, attrs: Attributes, buildParam: (i: number) => string, i?: number): Promise<number> {
163
- const stm = buildToInsertBatch(objs, table, attrs, buildParam, i);
179
+ export function insertBatch<T>(exec: (sql: string, args?: any[]) => Promise<number>, objs: T[], table: string, attrs: Attributes, buildParam: ((i: number) => string)|boolean, ver?: string, i?: number): Promise<number> {
180
+ const stm = buildToInsertBatch(objs, table, attrs, buildParam, ver, i);
164
181
  if (!stm) {
165
182
  return Promise.resolve(0);
166
183
  } else {
167
184
  return exec(stm.query, stm.params);
168
185
  }
169
186
  }
170
- export function buildToInsertBatch<T>(objs: T[], table: string, attrs: Attributes, buildParam: (i: number) => string, i?: number): Statement {
187
+ function buildOracleParam(i: number): string {
188
+ return ':' + i;
189
+ }
190
+ export function buildToInsertBatch<T>(objs: T[], table: string, attrs: Attributes, buildParam: ((i: number) => string) | boolean, ver?: string, i?: number): Statement|undefined {
171
191
  if (!i) {
172
192
  i = 1;
173
193
  }
174
194
  const ks = Object.keys(attrs);
175
- const cols: string[] = [];
176
- const rows: string[] = [];
177
195
  const args: any[] = [];
178
- for (const k of ks) {
179
- const attr = attrs[k];
180
- if (attr && !attr.ignored && !attr.noinsert) {
181
- const field = (attr.field ? attr.field : k);
182
- cols.push(field);
183
- }
184
- }
185
- for (const obj of objs) {
186
- const values: string[] = [];
196
+ if (buildParam && typeof buildParam === 'function') {
197
+ const cols: string[] = [];
198
+ const rows: string[] = [];
187
199
  for (const k of ks) {
188
200
  const attr = attrs[k];
189
201
  if (attr && !attr.ignored && !attr.noinsert) {
190
- let v = obj[k];
191
- if (v === undefined || v === null) {
192
- v = attr.default;
193
- }
194
- // let x: string;
195
- if (attr.version) {
196
- values.push('1');
197
- } else if (v === undefined || v == null) {
198
- values.push('null');
199
- } else if (v === '') {
200
- values.push(`''`);
201
- } else if (typeof v === 'number') {
202
- values.push(toString(v));
203
- } else if (typeof v === 'boolean') {
204
- if (attr.true === undefined) {
205
- if (v === true) {
206
- values.push(`true`);
202
+ const field = (attr.field ? attr.field : k);
203
+ cols.push(field);
204
+ }
205
+ }
206
+ for (const obj of objs) {
207
+ const values: string[] = [];
208
+ for (const k of ks) {
209
+ const attr = attrs[k];
210
+ if (attr && !attr.ignored && !attr.noinsert) {
211
+ let v = (obj as any)[k];
212
+ if (v === undefined || v === null) {
213
+ v = attr.default;
214
+ }
215
+ // let x: string;
216
+ if (attr.version) {
217
+ values.push('1');
218
+ } else if (v === undefined || v == null) {
219
+ values.push('null');
220
+ } else if (v === '') {
221
+ values.push(`''`);
222
+ } else if (typeof v === 'number') {
223
+ values.push(toString(v));
224
+ } else if (typeof v === 'boolean') {
225
+ if (attr.true === undefined) {
226
+ if (v === true) {
227
+ values.push(`true`);
228
+ } else {
229
+ values.push(`false`);
230
+ }
207
231
  } else {
208
- values.push(`false`);
232
+ const p = buildParam(i++);
233
+ values.push(p);
234
+ if (v === true) {
235
+ const v2 = (attr.true ? attr.true : '1');
236
+ args.push(v2);
237
+ } else {
238
+ const v2 = (attr.false ? attr.false : '0');
239
+ args.push(v2);
240
+ }
209
241
  }
210
242
  } else {
211
243
  const p = buildParam(i++);
212
244
  values.push(p);
213
- if (v === true) {
214
- const v2 = (attr.true ? attr.true : '1');
215
- args.push(v2);
245
+ args.push(v);
246
+ }
247
+ }
248
+ }
249
+ rows.push(`(${values.join(',')})`);
250
+ }
251
+ const query = `insert into ${table}(${cols.join(',')})values ${rows.join(',')}`;
252
+ return { query, params: args };
253
+ } else {
254
+ let notSkipInvalid = false;
255
+ if (buildParam === true) {
256
+ notSkipInvalid = true;
257
+ }
258
+ const rows: string[] = [];
259
+ for (const obj of objs) {
260
+ const cols: string[] = [];
261
+ const values: string[] = [];
262
+ let isVersion = false;
263
+ for (const k of ks) {
264
+ let v = (obj as any)[k];
265
+ const attr = attrs[k];
266
+ if (attr && !attr.ignored && !attr.noinsert) {
267
+ if (v === undefined || v == null) {
268
+ v = attr.default;
269
+ }
270
+ if (v !== undefined && v != null) {
271
+ const field = (attr.field ? attr.field : k);
272
+ cols.push(field);
273
+ if (k === ver) {
274
+ isVersion = true;
275
+ values.push(`${1}`);
216
276
  } else {
217
- const v2 = (attr.false ? attr.false : '0');
218
- args.push(v2);
277
+ if (v === '') {
278
+ values.push(`''`);
279
+ } else if (typeof v === 'number') {
280
+ values.push(toString(v));
281
+ } else if (typeof v === 'boolean') {
282
+ if (attr.true === undefined) {
283
+ if (v === true) {
284
+ values.push(`true`);
285
+ } else {
286
+ values.push(`false`);
287
+ }
288
+ } else {
289
+ const p = buildOracleParam(i++);
290
+ values.push(p);
291
+ if (v === true) {
292
+ const v2 = (attr.true ? attr.true : '1');
293
+ args.push(v2);
294
+ } else {
295
+ const v2 = (attr.false ? attr.false : '0');
296
+ args.push(v2);
297
+ }
298
+ }
299
+ } else {
300
+ const p = buildOracleParam(i++);
301
+ values.push(p);
302
+ args.push(v);
303
+ }
219
304
  }
220
305
  }
221
- } else {
222
- const p = buildParam(i++);
223
- values.push(p);
224
- args.push(v);
225
306
  }
226
307
  }
308
+ if (!isVersion && ver && ver.length > 0) {
309
+ const attr = attrs[ver];
310
+ const field = (attr.field ? attr.field : ver);
311
+ cols.push(field);
312
+ values.push(`${1}`);
313
+ }
314
+ if (cols.length === 0) {
315
+ if (notSkipInvalid) {
316
+ return undefined;
317
+ }
318
+ } else {
319
+ const s = `into ${table}(${cols.join(',')})values(${values.join(',')})`;
320
+ rows.push(s);
321
+ }
322
+ }
323
+ if (rows.length === 0) {
324
+ return undefined;
227
325
  }
228
- rows.push(`(${values.join(',')})`);
326
+ const query = `insert all ${rows.join(' ')} select * from dual`;
327
+ return { query, params: args };
229
328
  }
230
- const query = `insert into ${table}(${cols.join(',')})values ${rows.join(',')}`;
231
- return { query, params: args };
232
329
  }
233
330
  export function update<T>(exec: (sql: string, args?: any[]) => Promise<number>, obj: T, table: string, attrs: Attributes, buildParam: (i: number) => string, ver?: string, i?: number): Promise<number> {
234
331
  const stm = buildToUpdate(obj, table, attrs, buildParam, ver, i);
@@ -238,17 +335,18 @@ export function update<T>(exec: (sql: string, args?: any[]) => Promise<number>,
238
335
  return exec(stm.query, stm.params);
239
336
  }
240
337
  }
241
- export function buildToUpdate<T>(obj: T, table: string, attrs: Attributes, buildParam: (i: number) => string, ver?: string, i?: number): Statement {
338
+ export function buildToUpdate<T>(obj: T, table: string, attrs: Attributes, buildParam: (i: number) => string, ver?: string, i?: number): Statement|undefined {
242
339
  if (!i) {
243
340
  i = 1;
244
341
  }
342
+ const o: any = obj;
245
343
  const ks = Object.keys(attrs);
246
344
  const pks: Attribute[] = [];
247
345
  const colSet: string[] = [];
248
346
  const colQuery: string[] = [];
249
347
  const args: any[] = [];
250
348
  for (const k of ks) {
251
- const v = obj[k];
349
+ const v = o[k];
252
350
  if (v !== undefined) {
253
351
  const attr = attrs[k];
254
352
  attr.name = k;
@@ -291,11 +389,12 @@ export function buildToUpdate<T>(obj: T, table: string, attrs: Attributes, build
291
389
  }
292
390
  }
293
391
  for (const pk of pks) {
294
- const v = obj[pk.name];
392
+ const na = (pk.name ? pk.name : '');
393
+ const v = o[na];
295
394
  if (!v) {
296
- return null;
395
+ return undefined;
297
396
  } else {
298
- const attr = attrs[pk.name];
397
+ const attr = attrs[na];
299
398
  const field = (attr.field ? attr.field : pk.name);
300
399
  let x: string;
301
400
  if (v == null) {
@@ -322,7 +421,7 @@ export function buildToUpdate<T>(obj: T, table: string, attrs: Attributes, build
322
421
  }
323
422
  }
324
423
  if (ver && ver.length > 0) {
325
- const v = obj[ver];
424
+ const v = o[ver];
326
425
  if (typeof v === 'number' && !isNaN(v)) {
327
426
  const attr = attrs[ver];
328
427
  if (attr) {
@@ -333,7 +432,7 @@ export function buildToUpdate<T>(obj: T, table: string, attrs: Attributes, build
333
432
  }
334
433
  }
335
434
  if (colSet.length === 0 || colQuery.length === 0) {
336
- return null;
435
+ return undefined;
337
436
  } else {
338
437
  const query = `update ${table} set ${colSet.join(',')} where ${colQuery.join(' and ')}`;
339
438
  return { query, params: args };
@@ -347,22 +446,24 @@ export function updateBatch<T>(exec: (statements: Statement[]) => Promise<number
347
446
  return exec(stmts);
348
447
  }
349
448
  }
350
- export function buildToUpdateBatch<T>(objs: T[], table: string, attrs: Attributes, buildParam: (i: number) => string, notSkipInvalid?: boolean): Statement[] {
449
+ export function buildToUpdateBatch<T>(objs: T[], table: string, attrs: Attributes, buildParam: (i: number) => string, notSkipInvalid?: boolean): Statement[]|undefined {
351
450
  const sts: Statement[] = [];
352
451
  const meta = metadata(attrs);
353
452
  if (!meta.keys || meta.keys.length === 0) {
354
- return null;
453
+ return undefined;
355
454
  }
356
455
  for (const obj of objs) {
456
+ const o: any = obj;
357
457
  let i = 1;
358
- const ks = Object.keys(obj);
458
+ const ks = Object.keys(o);
359
459
  const colSet: string[] = [];
360
460
  const colQuery: string[] = [];
361
461
  const args: any[] = [];
362
462
  for (const k of ks) {
363
- const v = obj[k];
463
+ const v = o[k];
364
464
  if (v !== undefined) {
365
465
  const attr = attrs[k];
466
+ attr.name = k;
366
467
  if (attr && !attr.ignored && !attr.key && !attr.version && !attr.noupdate) {
367
468
  const field = (attr.field ? attr.field : k);
368
469
  let x: string;
@@ -399,11 +500,12 @@ export function buildToUpdateBatch<T>(objs: T[], table: string, attrs: Attribute
399
500
  }
400
501
  let valid = true;
401
502
  for (const pk of meta.keys) {
402
- const v = obj[pk.name];
503
+ const na = (pk.name ? pk.name : '');
504
+ const v = o[na];
403
505
  if (!v) {
404
506
  valid = false;
405
507
  } else {
406
- const attr = attrs[pk.name];
508
+ const attr = attrs[na];
407
509
  const field = (attr.field ? attr.field : pk.name);
408
510
  let x: string;
409
511
  if (v == null) {
@@ -431,12 +533,12 @@ export function buildToUpdateBatch<T>(objs: T[], table: string, attrs: Attribute
431
533
  }
432
534
  if (!valid || colSet.length === 0 || colQuery.length === 0) {
433
535
  if (notSkipInvalid) {
434
- return null;
536
+ return undefined;
435
537
  }
436
538
  } else {
437
539
  const ver = meta.version;
438
540
  if (ver && ver.length > 0) {
439
- const v = obj[ver];
541
+ const v = o[ver];
440
542
  if (typeof v === 'number' && !isNaN(v)) {
441
543
  const attr = attrs[ver];
442
544
  if (attr) {
@@ -453,7 +555,7 @@ export function buildToUpdateBatch<T>(objs: T[], table: string, attrs: Attribute
453
555
  }
454
556
  return sts;
455
557
  }
456
- export function version(attrs: Attributes): Attribute {
558
+ export function version(attrs: Attributes): Attribute|undefined {
457
559
  const ks = Object.keys(attrs);
458
560
  for (const k of ks) {
459
561
  const attr = attrs[k];
@@ -464,7 +566,7 @@ export function version(attrs: Attributes): Attribute {
464
566
  }
465
567
  return undefined;
466
568
  }
467
- export function key(attrs: Attributes): Attribute {
569
+ export function key(attrs: Attributes): Attribute|undefined {
468
570
  const ks = Object.keys(attrs);
469
571
  for (const k of ks) {
470
572
  const attr = attrs[k];
@@ -473,7 +575,7 @@ export function key(attrs: Attributes): Attribute {
473
575
  return attr;
474
576
  }
475
577
  }
476
- return null;
578
+ return undefined;
477
579
  }
478
580
  export function keys(attrs: Attributes): Attribute[] {
479
581
  const ks = Object.keys(attrs);
@@ -514,8 +616,8 @@ export function metadata(attrs: Attributes): Metadata {
514
616
  const ats: Attribute[] = [];
515
617
  const bools: Attribute[] = [];
516
618
  const fields: string[] = [];
517
- let ver: string;
518
619
  let isMap = false;
620
+ const m: Metadata = {keys: ats, fields};
519
621
  for (const k of ks) {
520
622
  const attr = attrs[k];
521
623
  attr.name = k;
@@ -529,7 +631,7 @@ export function metadata(attrs: Attributes): Metadata {
529
631
  bools.push(attr);
530
632
  }
531
633
  if (attr.version) {
532
- ver = k;
634
+ m.version = k;
533
635
  }
534
636
  const field = (attr.field ? attr.field : k);
535
637
  const s = field.toLowerCase();
@@ -538,7 +640,6 @@ export function metadata(attrs: Attributes): Metadata {
538
640
  isMap = true;
539
641
  }
540
642
  }
541
- const m: Metadata = {keys: ats, fields, version: ver};
542
643
  if (isMap) {
543
644
  m.map = mp;
544
645
  }
@@ -560,7 +661,7 @@ export function param(i: number): string {
560
661
  }
561
662
  export function setValue<T, V>(obj: T, path: string, value: V): void {
562
663
  const paths = path.split('.');
563
- let o = obj;
664
+ let o: any = obj;
564
665
  for (let i = 0; i < paths.length - 1; i++) {
565
666
  const p = paths[i];
566
667
  if (p in o) {