lt-open-data-sdk 1.0.0
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.
- package/LICENSE +21 -0
- package/README.md +366 -0
- package/dist/builder/FilterBuilder.d.ts +19 -0
- package/dist/builder/FilterBuilder.d.ts.map +1 -0
- package/dist/builder/FilterBuilder.js +178 -0
- package/dist/builder/FilterBuilder.js.map +1 -0
- package/dist/builder/QueryBuilder.d.ts +99 -0
- package/dist/builder/QueryBuilder.d.ts.map +1 -0
- package/dist/builder/QueryBuilder.js +162 -0
- package/dist/builder/QueryBuilder.js.map +1 -0
- package/dist/builder/index.d.ts +7 -0
- package/dist/builder/index.d.ts.map +1 -0
- package/dist/builder/index.js +6 -0
- package/dist/builder/index.js.map +1 -0
- package/dist/builder/types.d.ts +70 -0
- package/dist/builder/types.d.ts.map +1 -0
- package/dist/builder/types.js +5 -0
- package/dist/builder/types.js.map +1 -0
- package/dist/cli/crawler.d.ts +50 -0
- package/dist/cli/crawler.d.ts.map +1 -0
- package/dist/cli/crawler.js +161 -0
- package/dist/cli/crawler.js.map +1 -0
- package/dist/cli/generator.d.ts +9 -0
- package/dist/cli/generator.d.ts.map +1 -0
- package/dist/cli/generator.js +81 -0
- package/dist/cli/generator.js.map +1 -0
- package/dist/cli/index.d.ts +19 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +125 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/typeMapper.d.ts +34 -0
- package/dist/cli/typeMapper.d.ts.map +1 -0
- package/dist/cli/typeMapper.js +150 -0
- package/dist/cli/typeMapper.js.map +1 -0
- package/dist/client/SpintaClient.d.ts +168 -0
- package/dist/client/SpintaClient.d.ts.map +1 -0
- package/dist/client/SpintaClient.js +262 -0
- package/dist/client/SpintaClient.js.map +1 -0
- package/dist/client/auth.d.ts +31 -0
- package/dist/client/auth.d.ts.map +1 -0
- package/dist/client/auth.js +96 -0
- package/dist/client/auth.js.map +1 -0
- package/dist/client/errors.d.ts +35 -0
- package/dist/client/errors.d.ts.map +1 -0
- package/dist/client/errors.js +73 -0
- package/dist/client/errors.js.map +1 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +6 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/types.d.ts +96 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +5 -0
- package/dist/client/types.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QueryBuilder - Fluent interface for constructing Spinta DSQL query strings
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* const query = new QueryBuilder<City>()
|
|
7
|
+
* .select('name', 'population')
|
|
8
|
+
* .filter(f => f.field('country').eq('lt'))
|
|
9
|
+
* .sort('name')
|
|
10
|
+
* .limit(10);
|
|
11
|
+
*
|
|
12
|
+
* // Generates: ?select(name,population)&country="lt"&sort(name)&limit(10)
|
|
13
|
+
* const url = `/datasets/gov/example/City${query.toQueryString()}`;
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
import { FilterBuilder, filterToString } from './FilterBuilder.js';
|
|
17
|
+
export class QueryBuilder {
|
|
18
|
+
selectFields = [];
|
|
19
|
+
sortSpecs = [];
|
|
20
|
+
limitValue = null;
|
|
21
|
+
countMode = false;
|
|
22
|
+
filterExpression = null;
|
|
23
|
+
/**
|
|
24
|
+
* Select specific fields to return
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* .select('id', 'name') → ?select(id,name)
|
|
28
|
+
* .select('country.name') → ?select(country.name) // Supports dot notation for joins
|
|
29
|
+
*/
|
|
30
|
+
select(...fields) {
|
|
31
|
+
this.selectFields.push(...fields.map(String));
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Sort by field in ascending order
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* .sort('name') → ?sort(name)
|
|
39
|
+
*/
|
|
40
|
+
sort(field) {
|
|
41
|
+
this.sortSpecs.push({ field: String(field), direction: 'asc' });
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Sort by field in descending order
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* .sortDesc('date') → ?sort(-date)
|
|
49
|
+
*/
|
|
50
|
+
sortDesc(field) {
|
|
51
|
+
this.sortSpecs.push({ field: String(field), direction: 'desc' });
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Limit the number of results returned
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* .limit(10) → ?limit(10)
|
|
59
|
+
*/
|
|
60
|
+
limit(n) {
|
|
61
|
+
this.limitValue = n;
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Request count of objects instead of the objects themselves
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* .count() → ?count()
|
|
69
|
+
*/
|
|
70
|
+
count() {
|
|
71
|
+
this.countMode = true;
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Add filter conditions
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* // Simple equality
|
|
79
|
+
* .filter(f => f.field('code').eq('lt'))
|
|
80
|
+
*
|
|
81
|
+
* // String operations
|
|
82
|
+
* .filter(f => f.field('name').contains('Vilnius'))
|
|
83
|
+
*
|
|
84
|
+
* // AND combination
|
|
85
|
+
* .filter(f => f.field('a').eq(1).and(f.field('b').eq(2)))
|
|
86
|
+
*
|
|
87
|
+
* // OR combination
|
|
88
|
+
* .filter(f => f.field('a').eq(1).or(f.field('b').eq(2)))
|
|
89
|
+
*
|
|
90
|
+
* // Complex: OR inside AND (auto-wrapped in parens)
|
|
91
|
+
* .filter(f =>
|
|
92
|
+
* f.field('a').eq(1).and(
|
|
93
|
+
* f.field('b').eq(2).or(f.field('c').eq(3))
|
|
94
|
+
* )
|
|
95
|
+
* )
|
|
96
|
+
* // Generates: a=1&(b=2|c=3)
|
|
97
|
+
*/
|
|
98
|
+
filter(callback) {
|
|
99
|
+
const builder = new FilterBuilder();
|
|
100
|
+
const expr = callback(builder);
|
|
101
|
+
if (this.filterExpression !== null) {
|
|
102
|
+
// Combine with existing filter using AND
|
|
103
|
+
this.filterExpression = this.filterExpression.and(expr);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
this.filterExpression = expr;
|
|
107
|
+
}
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Generate the URL query string
|
|
112
|
+
*
|
|
113
|
+
* @returns Query string starting with '?' if there are any parameters, empty string otherwise
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* new QueryBuilder().select('name').sort('name').toQueryString()
|
|
117
|
+
* // Returns: '?select(name)&sort(name)'
|
|
118
|
+
*/
|
|
119
|
+
toQueryString() {
|
|
120
|
+
const parts = [];
|
|
121
|
+
// Select
|
|
122
|
+
if (this.selectFields.length > 0) {
|
|
123
|
+
parts.push(`select(${this.selectFields.join(',')})`);
|
|
124
|
+
}
|
|
125
|
+
// Filter
|
|
126
|
+
if (this.filterExpression !== null) {
|
|
127
|
+
parts.push(filterToString(this.filterExpression.node));
|
|
128
|
+
}
|
|
129
|
+
// Sort
|
|
130
|
+
if (this.sortSpecs.length > 0) {
|
|
131
|
+
const sortFields = this.sortSpecs.map((s) => s.direction === 'desc' ? `-${s.field}` : s.field);
|
|
132
|
+
parts.push(`sort(${sortFields.join(',')})`);
|
|
133
|
+
}
|
|
134
|
+
// Limit
|
|
135
|
+
if (this.limitValue !== null) {
|
|
136
|
+
parts.push(`limit(${String(this.limitValue)})`);
|
|
137
|
+
}
|
|
138
|
+
// Count
|
|
139
|
+
if (this.countMode) {
|
|
140
|
+
parts.push('count()');
|
|
141
|
+
}
|
|
142
|
+
if (parts.length === 0) {
|
|
143
|
+
return '';
|
|
144
|
+
}
|
|
145
|
+
// Join with & and prepend ?
|
|
146
|
+
// Note: The caller should handle full URL encoding if needed
|
|
147
|
+
return '?' + parts.join('&');
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Clone this query builder (useful for creating variants)
|
|
151
|
+
*/
|
|
152
|
+
clone() {
|
|
153
|
+
const copy = new QueryBuilder();
|
|
154
|
+
copy.selectFields = [...this.selectFields];
|
|
155
|
+
copy.sortSpecs = [...this.sortSpecs];
|
|
156
|
+
copy.limitValue = this.limitValue;
|
|
157
|
+
copy.countMode = this.countMode;
|
|
158
|
+
copy.filterExpression = this.filterExpression;
|
|
159
|
+
return copy;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=QueryBuilder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryBuilder.js","sourceRoot":"","sources":["../../src/builder/QueryBuilder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QueryBuilder module - Fluent interface for constructing Spinta DSQL queries
|
|
3
|
+
*/
|
|
4
|
+
export { QueryBuilder } from './QueryBuilder.js';
|
|
5
|
+
export { FilterBuilder, filterToString } from './FilterBuilder.js';
|
|
6
|
+
export type { FilterCallback, FilterExpression, FilterExpressionBuilder, ComparisonOperator, StringOperator, SortDirection, SortSpec, } from './types.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builder/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACnE,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,QAAQ,GACT,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/builder/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core type definitions for the QueryBuilder module
|
|
3
|
+
*/
|
|
4
|
+
/** Comparison operators for filtering */
|
|
5
|
+
export type ComparisonOperator = 'eq' | 'ne' | 'lt' | 'le' | 'gt' | 'ge';
|
|
6
|
+
/** String-specific operators */
|
|
7
|
+
export type StringOperator = 'contains' | 'startswith';
|
|
8
|
+
/** Sort direction */
|
|
9
|
+
export type SortDirection = 'asc' | 'desc';
|
|
10
|
+
/** Sort specification for a field */
|
|
11
|
+
export interface SortSpec {
|
|
12
|
+
field: string;
|
|
13
|
+
direction: SortDirection;
|
|
14
|
+
}
|
|
15
|
+
/** Base filter expression node */
|
|
16
|
+
export interface FilterNode {
|
|
17
|
+
type: 'comparison' | 'string_op' | 'and' | 'or';
|
|
18
|
+
}
|
|
19
|
+
/** Comparison filter expression */
|
|
20
|
+
export interface ComparisonNode extends FilterNode {
|
|
21
|
+
type: 'comparison';
|
|
22
|
+
field: string;
|
|
23
|
+
operator: ComparisonOperator;
|
|
24
|
+
value: unknown;
|
|
25
|
+
}
|
|
26
|
+
/** String operation filter expression */
|
|
27
|
+
export interface StringOpNode extends FilterNode {
|
|
28
|
+
type: 'string_op';
|
|
29
|
+
field: string;
|
|
30
|
+
operator: StringOperator;
|
|
31
|
+
value: string;
|
|
32
|
+
}
|
|
33
|
+
/** AND combination of filters */
|
|
34
|
+
export interface AndNode extends FilterNode {
|
|
35
|
+
type: 'and';
|
|
36
|
+
left: FilterExpression;
|
|
37
|
+
right: FilterExpression;
|
|
38
|
+
}
|
|
39
|
+
/** OR combination of filters */
|
|
40
|
+
export interface OrNode extends FilterNode {
|
|
41
|
+
type: 'or';
|
|
42
|
+
left: FilterExpression;
|
|
43
|
+
right: FilterExpression;
|
|
44
|
+
}
|
|
45
|
+
/** Union of all filter expression types */
|
|
46
|
+
export type FilterExpression = ComparisonNode | StringOpNode | AndNode | OrNode;
|
|
47
|
+
/** Callback type for building filter expressions */
|
|
48
|
+
export type FilterCallback<T> = (builder: FilterBuilderInterface<T>) => FilterExpressionBuilder;
|
|
49
|
+
/** Interface for field filter operations */
|
|
50
|
+
export interface FieldFilterInterface {
|
|
51
|
+
eq(value: unknown): FilterExpressionBuilder;
|
|
52
|
+
ne(value: unknown): FilterExpressionBuilder;
|
|
53
|
+
lt(value: unknown): FilterExpressionBuilder;
|
|
54
|
+
le(value: unknown): FilterExpressionBuilder;
|
|
55
|
+
gt(value: unknown): FilterExpressionBuilder;
|
|
56
|
+
ge(value: unknown): FilterExpressionBuilder;
|
|
57
|
+
contains(value: string): FilterExpressionBuilder;
|
|
58
|
+
startswith(value: string): FilterExpressionBuilder;
|
|
59
|
+
}
|
|
60
|
+
/** Interface for building filter expressions */
|
|
61
|
+
export interface FilterBuilderInterface<T> {
|
|
62
|
+
field(name: keyof T | string): FieldFilterInterface;
|
|
63
|
+
}
|
|
64
|
+
/** Filter expression with AND/OR combination methods */
|
|
65
|
+
export interface FilterExpressionBuilder {
|
|
66
|
+
readonly node: FilterExpression;
|
|
67
|
+
and(other: FilterExpressionBuilder): FilterExpressionBuilder;
|
|
68
|
+
or(other: FilterExpressionBuilder): FilterExpressionBuilder;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/builder/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,yCAAyC;AACzC,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEzE,gCAAgC;AAChC,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,YAAY,CAAC;AAEvD,qBAAqB;AACrB,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,CAAC;AAE3C,qCAAqC;AACrC,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,aAAa,CAAC;CAC1B;AAED,kCAAkC;AAClC,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,YAAY,GAAG,WAAW,GAAG,KAAK,GAAG,IAAI,CAAC;CACjD;AAED,mCAAmC;AACnC,MAAM,WAAW,cAAe,SAAQ,UAAU;IAChD,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,yCAAyC;AACzC,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC9C,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,iCAAiC;AACjC,MAAM,WAAW,OAAQ,SAAQ,UAAU;IACzC,IAAI,EAAE,KAAK,CAAC;IACZ,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAED,gCAAgC;AAChC,MAAM,WAAW,MAAO,SAAQ,UAAU;IACxC,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAED,2CAA2C;AAC3C,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG,YAAY,GAAG,OAAO,GAAG,MAAM,CAAC;AAEhF,oDAAoD;AACpD,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAC,CAAC,KAAK,uBAAuB,CAAC;AAEhG,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACnC,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,uBAAuB,CAAC;IAC5C,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,uBAAuB,CAAC;IAC5C,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,uBAAuB,CAAC;IAC5C,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,uBAAuB,CAAC;IAC5C,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,uBAAuB,CAAC;IAC5C,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,uBAAuB,CAAC;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,uBAAuB,CAAC;IACjD,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,uBAAuB,CAAC;CACpD;AAED,gDAAgD;AAChD,MAAM,WAAW,sBAAsB,CAAC,CAAC;IACvC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,MAAM,GAAG,oBAAoB,CAAC;CACrD;AAED,wDAAwD;AACxD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,GAAG,CAAC,KAAK,EAAE,uBAAuB,GAAG,uBAAuB,CAAC;IAC7D,EAAE,CAAC,KAAK,EAAE,uBAAuB,GAAG,uBAAuB,CAAC;CAC7D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/builder/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Namespace crawler for discovering models in the Spinta API
|
|
3
|
+
*/
|
|
4
|
+
import type { SpintaClient } from '../client/SpintaClient.js';
|
|
5
|
+
/** Model metadata from API */
|
|
6
|
+
export interface ModelMetadata {
|
|
7
|
+
path: string;
|
|
8
|
+
title?: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
properties: PropertyMetadata[];
|
|
11
|
+
}
|
|
12
|
+
/** Property metadata from API */
|
|
13
|
+
export interface PropertyMetadata {
|
|
14
|
+
name: string;
|
|
15
|
+
type: string;
|
|
16
|
+
ref?: string;
|
|
17
|
+
title?: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
}
|
|
20
|
+
/** Namespace entry */
|
|
21
|
+
export interface NamespaceEntry {
|
|
22
|
+
path: string;
|
|
23
|
+
type: 'ns' | 'model';
|
|
24
|
+
title?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Crawl a namespace and discover all models
|
|
28
|
+
*
|
|
29
|
+
* @param client - SpintaClient instance
|
|
30
|
+
* @param namespace - Starting namespace path
|
|
31
|
+
* @param recursive - Whether to recurse into sub-namespaces
|
|
32
|
+
* @returns Array of model paths discovered
|
|
33
|
+
*/
|
|
34
|
+
export declare function crawlNamespace(client: SpintaClient, namespace: string, recursive?: boolean): Promise<string[]>;
|
|
35
|
+
/**
|
|
36
|
+
* Fetch model metadata by sampling actual data
|
|
37
|
+
*
|
|
38
|
+
* Since the :schema endpoint requires authentication, we infer types
|
|
39
|
+
* from actual data by fetching a sample record.
|
|
40
|
+
*
|
|
41
|
+
* @param _client - SpintaClient instance (unused, using direct fetch)
|
|
42
|
+
* @param modelPath - Full model path
|
|
43
|
+
* @returns Model metadata with inferred properties
|
|
44
|
+
*/
|
|
45
|
+
export declare function fetchModelMetadata(_client: SpintaClient, modelPath: string): Promise<ModelMetadata>;
|
|
46
|
+
/**
|
|
47
|
+
* Fetch metadata for multiple models
|
|
48
|
+
*/
|
|
49
|
+
export declare function fetchAllModelsMetadata(client: SpintaClient, modelPaths: readonly string[]): Promise<ModelMetadata[]>;
|
|
50
|
+
//# sourceMappingURL=crawler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crawler.d.ts","sourceRoot":"","sources":["../../src/cli/crawler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D,8BAA8B;AAC9B,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAED,iCAAiC;AACjC,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,sBAAsB;AACtB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,MAAM,EACjB,SAAS,UAAO,GACf,OAAO,CAAC,MAAM,EAAE,CAAC,CAenB;AA4CD;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,CAAC,CA6ExB;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,OAAO,CAAC,aAAa,EAAE,CAAC,CAS1B"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Namespace crawler for discovering models in the Spinta API
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Crawl a namespace and discover all models
|
|
6
|
+
*
|
|
7
|
+
* @param client - SpintaClient instance
|
|
8
|
+
* @param namespace - Starting namespace path
|
|
9
|
+
* @param recursive - Whether to recurse into sub-namespaces
|
|
10
|
+
* @returns Array of model paths discovered
|
|
11
|
+
*/
|
|
12
|
+
export async function crawlNamespace(client, namespace, recursive = true) {
|
|
13
|
+
const entries = await client.listNamespace(namespace);
|
|
14
|
+
const models = [];
|
|
15
|
+
for (const entry of entries) {
|
|
16
|
+
if (entry._type === 'model') {
|
|
17
|
+
models.push(entry._id);
|
|
18
|
+
}
|
|
19
|
+
else if (recursive) {
|
|
20
|
+
// entry._type is 'ns' here (narrowed by TypeScript)
|
|
21
|
+
const subModels = await crawlNamespace(client, entry._id, true);
|
|
22
|
+
models.push(...subModels);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return models;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Infer type from a JavaScript value
|
|
29
|
+
*/
|
|
30
|
+
function inferType(value) {
|
|
31
|
+
if (value === null) {
|
|
32
|
+
return 'unknown';
|
|
33
|
+
}
|
|
34
|
+
if (typeof value === 'string') {
|
|
35
|
+
// Check for ISO date format
|
|
36
|
+
if (/^\d{4}-\d{2}-\d{2}/.test(value)) {
|
|
37
|
+
return value.includes('T') ? 'datetime' : 'date';
|
|
38
|
+
}
|
|
39
|
+
// Check for UUID (ref)
|
|
40
|
+
if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value)) {
|
|
41
|
+
return 'ref';
|
|
42
|
+
}
|
|
43
|
+
return 'string';
|
|
44
|
+
}
|
|
45
|
+
if (typeof value === 'number') {
|
|
46
|
+
return Number.isInteger(value) ? 'integer' : 'number';
|
|
47
|
+
}
|
|
48
|
+
if (typeof value === 'boolean') {
|
|
49
|
+
return 'boolean';
|
|
50
|
+
}
|
|
51
|
+
if (Array.isArray(value)) {
|
|
52
|
+
return 'array';
|
|
53
|
+
}
|
|
54
|
+
if (typeof value === 'object') {
|
|
55
|
+
// Check for ref object with _id
|
|
56
|
+
if ('_id' in value && typeof value._id === 'string') {
|
|
57
|
+
return 'ref';
|
|
58
|
+
}
|
|
59
|
+
return 'object';
|
|
60
|
+
}
|
|
61
|
+
return 'unknown';
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Fetch model metadata by sampling actual data
|
|
65
|
+
*
|
|
66
|
+
* Since the :schema endpoint requires authentication, we infer types
|
|
67
|
+
* from actual data by fetching a sample record.
|
|
68
|
+
*
|
|
69
|
+
* @param _client - SpintaClient instance (unused, using direct fetch)
|
|
70
|
+
* @param modelPath - Full model path
|
|
71
|
+
* @returns Model metadata with inferred properties
|
|
72
|
+
*/
|
|
73
|
+
export async function fetchModelMetadata(_client, modelPath) {
|
|
74
|
+
// Fetch sample records to infer property types
|
|
75
|
+
// Limit to 10 records to increase chance of finding non-null values
|
|
76
|
+
const url = `https://get.data.gov.lt/${modelPath}?limit(10)`;
|
|
77
|
+
try {
|
|
78
|
+
const response = await fetch(url);
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
throw new Error(`Failed to fetch model data: ${String(response.status)}`);
|
|
81
|
+
}
|
|
82
|
+
const data = (await response.json());
|
|
83
|
+
const properties = [];
|
|
84
|
+
const propertyTypes = new Map();
|
|
85
|
+
// Scan all fetched records
|
|
86
|
+
for (const record of data._data) {
|
|
87
|
+
for (const [key, value] of Object.entries(record)) {
|
|
88
|
+
// Skip internal Spinta fields
|
|
89
|
+
if (key.startsWith('_')) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const type = inferType(value);
|
|
93
|
+
if (!propertyTypes.has(key)) {
|
|
94
|
+
propertyTypes.set(key, new Set());
|
|
95
|
+
}
|
|
96
|
+
propertyTypes.get(key)?.add(type);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Resolve final types
|
|
100
|
+
for (const [key, types] of propertyTypes.entries()) {
|
|
101
|
+
let finalType = 'unknown';
|
|
102
|
+
// If we have concrete types, prioritize them over 'unknown'
|
|
103
|
+
if (types.size > 0) {
|
|
104
|
+
types.delete('unknown'); // Remove unknown from consideration if we have other types
|
|
105
|
+
}
|
|
106
|
+
if (types.size === 1) {
|
|
107
|
+
// Single concrete type found
|
|
108
|
+
finalType = types.values().next().value ?? 'unknown';
|
|
109
|
+
}
|
|
110
|
+
else if (types.size > 1) {
|
|
111
|
+
// Multiple types found
|
|
112
|
+
// Check for specific priority overrides
|
|
113
|
+
if (types.has('ref'))
|
|
114
|
+
finalType = 'ref';
|
|
115
|
+
else if (types.has('string'))
|
|
116
|
+
finalType = 'string'; // If mixed with string, it's a string
|
|
117
|
+
else if (types.has('datetime'))
|
|
118
|
+
finalType = 'datetime';
|
|
119
|
+
else if (types.has('date'))
|
|
120
|
+
finalType = 'date';
|
|
121
|
+
else if (types.has('number') || types.has('integer'))
|
|
122
|
+
finalType = 'number';
|
|
123
|
+
else
|
|
124
|
+
finalType = 'string'; // Fallback
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
// Only had unknown/null
|
|
128
|
+
finalType = 'unknown';
|
|
129
|
+
}
|
|
130
|
+
properties.push({
|
|
131
|
+
name: key,
|
|
132
|
+
type: finalType,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
path: modelPath,
|
|
137
|
+
properties,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
// Return minimal metadata on error
|
|
142
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
143
|
+
console.error(`Warning: Could not fetch data for ${modelPath}: ${errorMessage}`);
|
|
144
|
+
return {
|
|
145
|
+
path: modelPath,
|
|
146
|
+
properties: [],
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Fetch metadata for multiple models
|
|
152
|
+
*/
|
|
153
|
+
export async function fetchAllModelsMetadata(client, modelPaths) {
|
|
154
|
+
const metadata = [];
|
|
155
|
+
for (const path of modelPaths) {
|
|
156
|
+
const meta = await fetchModelMetadata(client, path);
|
|
157
|
+
metadata.push(meta);
|
|
158
|
+
}
|
|
159
|
+
return metadata;
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=crawler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crawler.js","sourceRoot":"","sources":["../../src/cli/crawler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript declaration file generator
|
|
3
|
+
*/
|
|
4
|
+
import type { ModelMetadata } from './crawler.js';
|
|
5
|
+
/**
|
|
6
|
+
* Generate a complete .d.ts file from model metadata
|
|
7
|
+
*/
|
|
8
|
+
export declare function generateDeclarationFile(models: readonly ModelMetadata[], namespace: string): string;
|
|
9
|
+
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/cli/generator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AA6DlD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,SAAS,EAAE,MAAM,GAChB,MAAM,CAqCR"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript declaration file generator
|
|
3
|
+
*/
|
|
4
|
+
import { mapSpintaType, isRequired, modelPathToInterfaceName, sanitizePropertyName, generateJsDoc, } from './typeMapper.js';
|
|
5
|
+
/**
|
|
6
|
+
* Generate a TypeScript interface from model metadata
|
|
7
|
+
*/
|
|
8
|
+
function generateInterface(model) {
|
|
9
|
+
const interfaceName = modelPathToInterfaceName(model.path);
|
|
10
|
+
const lines = [];
|
|
11
|
+
// Add JSDoc
|
|
12
|
+
const jsDoc = generateJsDoc(model.title, model.description);
|
|
13
|
+
if (jsDoc !== '') {
|
|
14
|
+
lines.push(jsDoc);
|
|
15
|
+
}
|
|
16
|
+
lines.push(`export interface ${interfaceName} {`);
|
|
17
|
+
// Add base Spinta object properties
|
|
18
|
+
lines.push(' /** Unique object identifier */');
|
|
19
|
+
lines.push(' _id: string;');
|
|
20
|
+
lines.push(' /** Model type path */');
|
|
21
|
+
lines.push(' _type: string;');
|
|
22
|
+
lines.push(' /** Object revision (for optimistic locking) */');
|
|
23
|
+
lines.push(' _revision?: string;');
|
|
24
|
+
lines.push(' /** Transaction ID */');
|
|
25
|
+
lines.push(' _txn?: string;');
|
|
26
|
+
// Add model properties
|
|
27
|
+
for (const prop of model.properties) {
|
|
28
|
+
const propName = sanitizePropertyName(prop.name);
|
|
29
|
+
const tsType = mapSpintaType(prop.type);
|
|
30
|
+
const required = isRequired(prop.type);
|
|
31
|
+
const optional = required ? '' : '?';
|
|
32
|
+
// Add property JSDoc
|
|
33
|
+
const propJsDoc = generateJsDoc(prop.title, prop.description);
|
|
34
|
+
if (propJsDoc !== '') {
|
|
35
|
+
lines.push('');
|
|
36
|
+
lines.push(propJsDoc
|
|
37
|
+
.split('\n')
|
|
38
|
+
.map((l) => ' ' + l)
|
|
39
|
+
.join('\n'));
|
|
40
|
+
}
|
|
41
|
+
lines.push(` ${propName}${optional}: ${tsType};`);
|
|
42
|
+
}
|
|
43
|
+
lines.push('}');
|
|
44
|
+
return lines.join('\n');
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Generate a complete .d.ts file from model metadata
|
|
48
|
+
*/
|
|
49
|
+
export function generateDeclarationFile(models, namespace) {
|
|
50
|
+
const lines = [];
|
|
51
|
+
// File header
|
|
52
|
+
lines.push('/**');
|
|
53
|
+
lines.push(` * TypeScript definitions for ${namespace}`);
|
|
54
|
+
lines.push(' * ');
|
|
55
|
+
lines.push(' * Generated by lt-data-sdk CLI');
|
|
56
|
+
lines.push(` * Generated at: ${new Date().toISOString()}`);
|
|
57
|
+
lines.push(' * ');
|
|
58
|
+
lines.push(' * @see https://get.data.gov.lt/' + namespace);
|
|
59
|
+
lines.push(' */');
|
|
60
|
+
lines.push('');
|
|
61
|
+
// Generate each interface
|
|
62
|
+
for (const model of models) {
|
|
63
|
+
lines.push(generateInterface(model));
|
|
64
|
+
lines.push('');
|
|
65
|
+
}
|
|
66
|
+
// Generate namespace map type for convenience
|
|
67
|
+
if (models.length > 0) {
|
|
68
|
+
lines.push('/**');
|
|
69
|
+
lines.push(' * Map of all models in this namespace');
|
|
70
|
+
lines.push(' * Use with SpintaClient for type-safe queries');
|
|
71
|
+
lines.push(' */');
|
|
72
|
+
lines.push('export interface ModelMap {');
|
|
73
|
+
for (const model of models) {
|
|
74
|
+
const interfaceName = modelPathToInterfaceName(model.path);
|
|
75
|
+
lines.push(` '${model.path}': ${interfaceName};`);
|
|
76
|
+
}
|
|
77
|
+
lines.push('}');
|
|
78
|
+
}
|
|
79
|
+
return lines.join('\n');
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/cli/generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* lt-gen CLI - Generate TypeScript definitions from Spinta API metadata
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* npx lt-gen <namespace> [options]
|
|
7
|
+
*
|
|
8
|
+
* Examples:
|
|
9
|
+
* npx lt-gen datasets/gov/ivpk/adk
|
|
10
|
+
* npx lt-gen datasets/gov/ivpk/adk --output ./types/adk.d.ts
|
|
11
|
+
* npx lt-gen datasets/gov/ivpk/adk --base-url https://get.data.gov.lt
|
|
12
|
+
*
|
|
13
|
+
* Options:
|
|
14
|
+
* --output, -o Output file path (default: stdout)
|
|
15
|
+
* --base-url Base URL for the API (default: https://get.data.gov.lt)
|
|
16
|
+
* --help, -h Show help
|
|
17
|
+
*/
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG"}
|