@ductape/sdk 0.0.4-v42 → 0.0.4-v44
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/dist/apps/services/app.service.d.ts +10 -0
- package/dist/apps/services/app.service.js +38 -69
- package/dist/apps/services/app.service.js.map +1 -1
- package/dist/apps/validators/joi-validators/create.appWebhook.validator.d.ts +1 -2
- package/dist/apps/validators/joi-validators/create.appWebhook.validator.js +2 -15
- package/dist/apps/validators/joi-validators/create.appWebhook.validator.js.map +1 -1
- package/dist/apps/validators/joi-validators/update.appWebhook.validator.d.ts +1 -2
- package/dist/apps/validators/joi-validators/update.appWebhook.validator.js +2 -14
- package/dist/apps/validators/joi-validators/update.appWebhook.validator.js.map +1 -1
- package/dist/database/adapters/base.adapter.d.ts +176 -0
- package/dist/database/adapters/base.adapter.js +31 -0
- package/dist/database/adapters/base.adapter.js.map +1 -0
- package/dist/database/adapters/dynamodb.adapter.d.ts +91 -0
- package/dist/database/adapters/dynamodb.adapter.js +1469 -0
- package/dist/database/adapters/dynamodb.adapter.js.map +1 -0
- package/dist/database/adapters/mongodb.adapter.d.ts +71 -0
- package/dist/database/adapters/mongodb.adapter.js +882 -0
- package/dist/database/adapters/mongodb.adapter.js.map +1 -0
- package/dist/database/adapters/mysql.adapter.d.ts +146 -0
- package/dist/database/adapters/mysql.adapter.js +1417 -0
- package/dist/database/adapters/mysql.adapter.js.map +1 -0
- package/dist/database/adapters/postgresql.adapter.d.ts +147 -0
- package/dist/database/adapters/postgresql.adapter.js +1472 -0
- package/dist/database/adapters/postgresql.adapter.js.map +1 -0
- package/dist/database/database.service.d.ts +195 -0
- package/dist/database/database.service.js +502 -0
- package/dist/database/database.service.js.map +1 -0
- package/dist/database/index.d.ts +18 -0
- package/dist/database/index.js +98 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/types/aggregation.types.d.ts +202 -0
- package/dist/database/types/aggregation.types.js +21 -0
- package/dist/database/types/aggregation.types.js.map +1 -0
- package/dist/database/types/connection.types.d.ts +132 -0
- package/dist/database/types/connection.types.js +6 -0
- package/dist/database/types/connection.types.js.map +1 -0
- package/dist/database/types/database.types.d.ts +174 -0
- package/dist/database/types/database.types.js +74 -0
- package/dist/database/types/database.types.js.map +1 -0
- package/dist/database/types/index.d.ts +12 -0
- package/dist/database/types/index.js +37 -0
- package/dist/database/types/index.js.map +1 -0
- package/dist/database/types/index.types.d.ts +220 -0
- package/dist/database/types/index.types.js +27 -0
- package/dist/database/types/index.types.js.map +1 -0
- package/dist/database/types/migration.types.d.ts +205 -0
- package/dist/database/types/migration.types.js +44 -0
- package/dist/database/types/migration.types.js.map +1 -0
- package/dist/database/types/query.types.d.ts +305 -0
- package/dist/database/types/query.types.js +57 -0
- package/dist/database/types/query.types.js.map +1 -0
- package/dist/database/types/result.types.d.ts +218 -0
- package/dist/database/types/result.types.js +6 -0
- package/dist/database/types/result.types.js.map +1 -0
- package/dist/database/types/schema.types.d.ts +190 -0
- package/dist/database/types/schema.types.js +69 -0
- package/dist/database/types/schema.types.js.map +1 -0
- package/dist/database/utils/helpers.d.ts +66 -0
- package/dist/database/utils/helpers.js +501 -0
- package/dist/database/utils/helpers.js.map +1 -0
- package/dist/database/utils/migration.utils.d.ts +151 -0
- package/dist/database/utils/migration.utils.js +476 -0
- package/dist/database/utils/migration.utils.js.map +1 -0
- package/dist/database/utils/transaction.d.ts +64 -0
- package/dist/database/utils/transaction.js +130 -0
- package/dist/database/utils/transaction.js.map +1 -0
- package/dist/database/validators/connection.validator.d.ts +20 -0
- package/dist/database/validators/connection.validator.js +267 -0
- package/dist/database/validators/connection.validator.js.map +1 -0
- package/dist/database/validators/query.validator.d.ts +31 -0
- package/dist/database/validators/query.validator.js +305 -0
- package/dist/database/validators/query.validator.js.map +1 -0
- package/dist/database/validators/schema.validator.d.ts +31 -0
- package/dist/database/validators/schema.validator.js +334 -0
- package/dist/database/validators/schema.validator.js.map +1 -0
- package/dist/index.d.ts +194 -146
- package/dist/index.js +232 -173
- package/dist/index.js.map +1 -1
- package/dist/processor/services/processor.service.js +61 -43
- package/dist/processor/services/processor.service.js.map +1 -1
- package/dist/test/test.processor.js +1 -3
- package/dist/test/test.processor.js.map +1 -1
- package/dist/types/appBuilder.types.d.ts +1 -1
- package/dist/types/processor.types.d.ts +2 -2
- package/package.json +3 -1
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema type definitions for tables, columns, and data types
|
|
3
|
+
* Provides unified interface for SQL and NoSQL schema operations
|
|
4
|
+
*/
|
|
5
|
+
import type { IIndexDefinition } from './index.types';
|
|
6
|
+
/**
|
|
7
|
+
* Column data types (unified across SQL and NoSQL)
|
|
8
|
+
*/
|
|
9
|
+
export declare enum ColumnType {
|
|
10
|
+
STRING = "string",
|
|
11
|
+
TEXT = "text",
|
|
12
|
+
VARCHAR = "varchar",
|
|
13
|
+
CHAR = "char",
|
|
14
|
+
INTEGER = "integer",
|
|
15
|
+
BIGINT = "bigint",
|
|
16
|
+
SMALLINT = "smallint",
|
|
17
|
+
DECIMAL = "decimal",
|
|
18
|
+
NUMERIC = "numeric",
|
|
19
|
+
FLOAT = "float",
|
|
20
|
+
DOUBLE = "double",
|
|
21
|
+
REAL = "real",
|
|
22
|
+
BOOLEAN = "boolean",
|
|
23
|
+
DATE = "date",
|
|
24
|
+
TIME = "time",
|
|
25
|
+
DATETIME = "datetime",
|
|
26
|
+
TIMESTAMP = "timestamp",
|
|
27
|
+
JSON = "json",
|
|
28
|
+
JSONB = "jsonb",
|
|
29
|
+
OBJECT = "object",
|
|
30
|
+
ARRAY = "array",
|
|
31
|
+
BINARY = "binary",
|
|
32
|
+
BLOB = "blob",
|
|
33
|
+
UUID = "uuid",
|
|
34
|
+
ENUM = "enum"
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Column constraint types
|
|
38
|
+
*/
|
|
39
|
+
export declare enum ConstraintType {
|
|
40
|
+
PRIMARY_KEY = "primary_key",
|
|
41
|
+
FOREIGN_KEY = "foreign_key",
|
|
42
|
+
UNIQUE = "unique",
|
|
43
|
+
NOT_NULL = "not_null",
|
|
44
|
+
DEFAULT = "default",
|
|
45
|
+
CHECK = "check",
|
|
46
|
+
INDEX = "index"
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Column definition
|
|
50
|
+
*/
|
|
51
|
+
export interface IColumnDefinition {
|
|
52
|
+
/** Column name */
|
|
53
|
+
name: string;
|
|
54
|
+
/** Column type */
|
|
55
|
+
type: ColumnType;
|
|
56
|
+
/** Is column nullable */
|
|
57
|
+
nullable?: boolean;
|
|
58
|
+
/** Default value */
|
|
59
|
+
defaultValue?: any;
|
|
60
|
+
/** Is primary key */
|
|
61
|
+
primaryKey?: boolean;
|
|
62
|
+
/** Is unique */
|
|
63
|
+
unique?: boolean;
|
|
64
|
+
/** Is auto-increment */
|
|
65
|
+
autoIncrement?: boolean;
|
|
66
|
+
/** Column length (for string types) */
|
|
67
|
+
length?: number;
|
|
68
|
+
/** Precision (for decimal/numeric) */
|
|
69
|
+
precision?: number;
|
|
70
|
+
/** Scale (for decimal/numeric) */
|
|
71
|
+
scale?: number;
|
|
72
|
+
/** Enum values (for enum type) */
|
|
73
|
+
enumValues?: string[];
|
|
74
|
+
/** Foreign key reference */
|
|
75
|
+
foreignKey?: IForeignKeyDefinition;
|
|
76
|
+
/** Check constraint */
|
|
77
|
+
check?: string;
|
|
78
|
+
/** Comment */
|
|
79
|
+
comment?: string;
|
|
80
|
+
/** For nested objects (NoSQL) */
|
|
81
|
+
nested?: INestedFieldDefinition;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Foreign key definition
|
|
85
|
+
*/
|
|
86
|
+
export interface IForeignKeyDefinition {
|
|
87
|
+
/** Referenced table */
|
|
88
|
+
table: string;
|
|
89
|
+
/** Referenced column */
|
|
90
|
+
column: string;
|
|
91
|
+
/** On delete action */
|
|
92
|
+
onDelete?: 'CASCADE' | 'SET NULL' | 'NO ACTION' | 'RESTRICT';
|
|
93
|
+
/** On update action */
|
|
94
|
+
onUpdate?: 'CASCADE' | 'SET NULL' | 'NO ACTION' | 'RESTRICT';
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Nested field definition (for NoSQL/JSON columns)
|
|
98
|
+
*/
|
|
99
|
+
export interface INestedFieldDefinition {
|
|
100
|
+
/** Nested field type */
|
|
101
|
+
type: ColumnType;
|
|
102
|
+
/** Is array of values */
|
|
103
|
+
isArray?: boolean;
|
|
104
|
+
/** Child fields (for nested objects) */
|
|
105
|
+
fields?: Record<string, INestedFieldDefinition>;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Table schema definition
|
|
109
|
+
*/
|
|
110
|
+
export interface ITableSchema {
|
|
111
|
+
/** Table/Collection name */
|
|
112
|
+
name: string;
|
|
113
|
+
/** Column definitions */
|
|
114
|
+
columns: IColumnDefinition[];
|
|
115
|
+
/** Primary key columns (composite keys) */
|
|
116
|
+
primaryKeys?: string[];
|
|
117
|
+
/** Indexes */
|
|
118
|
+
indexes?: IIndexDefinition[];
|
|
119
|
+
/** Unique constraints */
|
|
120
|
+
uniqueConstraints?: string[][];
|
|
121
|
+
/** Check constraints */
|
|
122
|
+
checkConstraints?: Array<{
|
|
123
|
+
name: string;
|
|
124
|
+
expression: string;
|
|
125
|
+
}>;
|
|
126
|
+
/** Table comment */
|
|
127
|
+
comment?: string;
|
|
128
|
+
/** Table options (engine, charset, etc.) */
|
|
129
|
+
options?: Record<string, any>;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Column alteration types
|
|
133
|
+
*/
|
|
134
|
+
export declare enum ColumnAlterationType {
|
|
135
|
+
ADD = "add",
|
|
136
|
+
MODIFY = "modify",
|
|
137
|
+
DROP = "drop",
|
|
138
|
+
RENAME = "rename"
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Column alteration operation
|
|
142
|
+
*/
|
|
143
|
+
export interface IColumnAlteration {
|
|
144
|
+
/** Type of alteration */
|
|
145
|
+
type: ColumnAlterationType;
|
|
146
|
+
/** Column definition (for ADD/MODIFY) */
|
|
147
|
+
column?: IColumnDefinition;
|
|
148
|
+
/** Old column name (for RENAME) */
|
|
149
|
+
oldName?: string;
|
|
150
|
+
/** New column name (for RENAME) */
|
|
151
|
+
newName?: string;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Schema validation result
|
|
155
|
+
*/
|
|
156
|
+
export interface ISchemaValidationResult {
|
|
157
|
+
/** Is schema valid */
|
|
158
|
+
valid: boolean;
|
|
159
|
+
/** Validation errors */
|
|
160
|
+
errors: Array<{
|
|
161
|
+
field: string;
|
|
162
|
+
message: string;
|
|
163
|
+
}>;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Table creation options
|
|
167
|
+
*/
|
|
168
|
+
export interface ICreateTableOptions {
|
|
169
|
+
/** Create if not exists */
|
|
170
|
+
ifNotExists?: boolean;
|
|
171
|
+
/** Table comment */
|
|
172
|
+
comment?: string;
|
|
173
|
+
/** Table engine (MySQL) */
|
|
174
|
+
engine?: string;
|
|
175
|
+
/** Character set (MySQL) */
|
|
176
|
+
charset?: string;
|
|
177
|
+
/** Collation */
|
|
178
|
+
collate?: string;
|
|
179
|
+
/** Additional options */
|
|
180
|
+
options?: Record<string, any>;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Table alteration options
|
|
184
|
+
*/
|
|
185
|
+
export interface IAlterTableOptions {
|
|
186
|
+
/** Generate migration */
|
|
187
|
+
generateMigration?: boolean;
|
|
188
|
+
/** Migration name */
|
|
189
|
+
migrationName?: string;
|
|
190
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Schema type definitions for tables, columns, and data types
|
|
4
|
+
* Provides unified interface for SQL and NoSQL schema operations
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.ColumnAlterationType = exports.ConstraintType = exports.ColumnType = void 0;
|
|
8
|
+
/**
|
|
9
|
+
* Column data types (unified across SQL and NoSQL)
|
|
10
|
+
*/
|
|
11
|
+
var ColumnType;
|
|
12
|
+
(function (ColumnType) {
|
|
13
|
+
// String types
|
|
14
|
+
ColumnType["STRING"] = "string";
|
|
15
|
+
ColumnType["TEXT"] = "text";
|
|
16
|
+
ColumnType["VARCHAR"] = "varchar";
|
|
17
|
+
ColumnType["CHAR"] = "char";
|
|
18
|
+
// Number types
|
|
19
|
+
ColumnType["INTEGER"] = "integer";
|
|
20
|
+
ColumnType["BIGINT"] = "bigint";
|
|
21
|
+
ColumnType["SMALLINT"] = "smallint";
|
|
22
|
+
ColumnType["DECIMAL"] = "decimal";
|
|
23
|
+
ColumnType["NUMERIC"] = "numeric";
|
|
24
|
+
ColumnType["FLOAT"] = "float";
|
|
25
|
+
ColumnType["DOUBLE"] = "double";
|
|
26
|
+
ColumnType["REAL"] = "real";
|
|
27
|
+
// Boolean
|
|
28
|
+
ColumnType["BOOLEAN"] = "boolean";
|
|
29
|
+
// Date/Time types
|
|
30
|
+
ColumnType["DATE"] = "date";
|
|
31
|
+
ColumnType["TIME"] = "time";
|
|
32
|
+
ColumnType["DATETIME"] = "datetime";
|
|
33
|
+
ColumnType["TIMESTAMP"] = "timestamp";
|
|
34
|
+
// JSON/Object types
|
|
35
|
+
ColumnType["JSON"] = "json";
|
|
36
|
+
ColumnType["JSONB"] = "jsonb";
|
|
37
|
+
ColumnType["OBJECT"] = "object";
|
|
38
|
+
ColumnType["ARRAY"] = "array";
|
|
39
|
+
// Binary
|
|
40
|
+
ColumnType["BINARY"] = "binary";
|
|
41
|
+
ColumnType["BLOB"] = "blob";
|
|
42
|
+
// Special types
|
|
43
|
+
ColumnType["UUID"] = "uuid";
|
|
44
|
+
ColumnType["ENUM"] = "enum";
|
|
45
|
+
})(ColumnType || (exports.ColumnType = ColumnType = {}));
|
|
46
|
+
/**
|
|
47
|
+
* Column constraint types
|
|
48
|
+
*/
|
|
49
|
+
var ConstraintType;
|
|
50
|
+
(function (ConstraintType) {
|
|
51
|
+
ConstraintType["PRIMARY_KEY"] = "primary_key";
|
|
52
|
+
ConstraintType["FOREIGN_KEY"] = "foreign_key";
|
|
53
|
+
ConstraintType["UNIQUE"] = "unique";
|
|
54
|
+
ConstraintType["NOT_NULL"] = "not_null";
|
|
55
|
+
ConstraintType["DEFAULT"] = "default";
|
|
56
|
+
ConstraintType["CHECK"] = "check";
|
|
57
|
+
ConstraintType["INDEX"] = "index";
|
|
58
|
+
})(ConstraintType || (exports.ConstraintType = ConstraintType = {}));
|
|
59
|
+
/**
|
|
60
|
+
* Column alteration types
|
|
61
|
+
*/
|
|
62
|
+
var ColumnAlterationType;
|
|
63
|
+
(function (ColumnAlterationType) {
|
|
64
|
+
ColumnAlterationType["ADD"] = "add";
|
|
65
|
+
ColumnAlterationType["MODIFY"] = "modify";
|
|
66
|
+
ColumnAlterationType["DROP"] = "drop";
|
|
67
|
+
ColumnAlterationType["RENAME"] = "rename";
|
|
68
|
+
})(ColumnAlterationType || (exports.ColumnAlterationType = ColumnAlterationType = {}));
|
|
69
|
+
//# sourceMappingURL=schema.types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.types.js","sourceRoot":"","sources":["../../../src/database/types/schema.types.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIH;;GAEG;AACH,IAAY,UAuCX;AAvCD,WAAY,UAAU;IACpB,eAAe;IACf,+BAAiB,CAAA;IACjB,2BAAa,CAAA;IACb,iCAAmB,CAAA;IACnB,2BAAa,CAAA;IAEb,eAAe;IACf,iCAAmB,CAAA;IACnB,+BAAiB,CAAA;IACjB,mCAAqB,CAAA;IACrB,iCAAmB,CAAA;IACnB,iCAAmB,CAAA;IACnB,6BAAe,CAAA;IACf,+BAAiB,CAAA;IACjB,2BAAa,CAAA;IAEb,UAAU;IACV,iCAAmB,CAAA;IAEnB,kBAAkB;IAClB,2BAAa,CAAA;IACb,2BAAa,CAAA;IACb,mCAAqB,CAAA;IACrB,qCAAuB,CAAA;IAEvB,oBAAoB;IACpB,2BAAa,CAAA;IACb,6BAAe,CAAA;IACf,+BAAiB,CAAA;IACjB,6BAAe,CAAA;IAEf,SAAS;IACT,+BAAiB,CAAA;IACjB,2BAAa,CAAA;IAEb,gBAAgB;IAChB,2BAAa,CAAA;IACb,2BAAa,CAAA;AACf,CAAC,EAvCW,UAAU,0BAAV,UAAU,QAuCrB;AAED;;GAEG;AACH,IAAY,cAQX;AARD,WAAY,cAAc;IACxB,6CAA2B,CAAA;IAC3B,6CAA2B,CAAA;IAC3B,mCAAiB,CAAA;IACjB,uCAAqB,CAAA;IACrB,qCAAmB,CAAA;IACnB,iCAAe,CAAA;IACf,iCAAe,CAAA;AACjB,CAAC,EARW,cAAc,8BAAd,cAAc,QAQzB;AAyFD;;GAEG;AACH,IAAY,oBAKX;AALD,WAAY,oBAAoB;IAC9B,mCAAW,CAAA;IACX,yCAAiB,CAAA;IACjB,qCAAa,CAAA;IACb,yCAAiB,CAAA;AACnB,CAAC,EALW,oBAAoB,oCAApB,oBAAoB,QAK/B"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Helper Utilities
|
|
3
|
+
* Type mapping, query building, and error handling utilities
|
|
4
|
+
*/
|
|
5
|
+
import { ColumnType } from '../types/schema.types';
|
|
6
|
+
import { DatabaseType } from '../types/database.types';
|
|
7
|
+
import { WhereClause } from '../types/query.types';
|
|
8
|
+
/**
|
|
9
|
+
* Map generic column types to database-specific types
|
|
10
|
+
*/
|
|
11
|
+
export declare function mapColumnTypeToNative(type: ColumnType, dbType: DatabaseType): string;
|
|
12
|
+
/**
|
|
13
|
+
* Build WHERE clause string for SQL databases from WhereClause
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildWhereClause(where: WhereClause, paramIndex?: number): {
|
|
16
|
+
sql: string;
|
|
17
|
+
params: any[];
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Build MongoDB query from WhereClause
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildMongoQuery(where: WhereClause): any;
|
|
23
|
+
/**
|
|
24
|
+
* Escape identifier (table/column name) for SQL
|
|
25
|
+
*/
|
|
26
|
+
export declare function escapeIdentifier(identifier: string, dbType: DatabaseType): string;
|
|
27
|
+
/**
|
|
28
|
+
* Escape string value for SQL
|
|
29
|
+
*/
|
|
30
|
+
export declare function escapeValue(value: any): string;
|
|
31
|
+
/**
|
|
32
|
+
* Format error message with context
|
|
33
|
+
*/
|
|
34
|
+
export declare function formatDatabaseError(error: any, operation: string, tableName?: string): Error;
|
|
35
|
+
/**
|
|
36
|
+
* Check if error is a connection error
|
|
37
|
+
*/
|
|
38
|
+
export declare function isConnectionError(error: any): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Check if error is a duplicate key error
|
|
41
|
+
*/
|
|
42
|
+
export declare function isDuplicateKeyError(error: any): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Check if error is a foreign key constraint error
|
|
45
|
+
*/
|
|
46
|
+
export declare function isForeignKeyError(error: any): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Retry a database operation with exponential backoff
|
|
49
|
+
*/
|
|
50
|
+
export declare function retryOperation<T>(operation: () => Promise<T>, maxRetries?: number, initialDelay?: number): Promise<T>;
|
|
51
|
+
/**
|
|
52
|
+
* Sanitize table name to prevent SQL injection
|
|
53
|
+
*/
|
|
54
|
+
export declare function sanitizeTableName(tableName: string): string;
|
|
55
|
+
/**
|
|
56
|
+
* Convert camelCase to snake_case
|
|
57
|
+
*/
|
|
58
|
+
export declare function camelToSnake(str: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* Convert snake_case to camelCase
|
|
61
|
+
*/
|
|
62
|
+
export declare function snakeToCamel(str: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* Deep clone an object
|
|
65
|
+
*/
|
|
66
|
+
export declare function deepClone<T>(obj: T): T;
|