@objectstack/objectql 3.0.3 → 3.0.4
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +17 -0
- package/README.md +94 -1
- package/dist/index.d.mts +117 -2
- package/dist/index.d.ts +117 -2
- package/dist/index.js +105 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +101 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/index.ts +16 -0
- package/src/kernel-factory.ts +48 -0
- package/src/util.test.ts +226 -0
- package/src/util.ts +219 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @objectstack/objectql@3.0.
|
|
2
|
+
> @objectstack/objectql@3.0.4 build /home/runner/work/spec/spec/packages/objectql
|
|
3
3
|
> tsup --config ../../tsup.config.ts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mESM[39m Build start
|
|
12
12
|
[34mCJS[39m Build start
|
|
13
|
-
[
|
|
14
|
-
[
|
|
15
|
-
[
|
|
16
|
-
[
|
|
17
|
-
[
|
|
18
|
-
[
|
|
13
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m82.74 KB[39m
|
|
14
|
+
[32mESM[39m [1mdist/index.mjs.map [22m[32m169.75 KB[39m
|
|
15
|
+
[32mESM[39m ⚡️ Build success in 118ms
|
|
16
|
+
[32mCJS[39m [1mdist/index.js [22m[32m84.46 KB[39m
|
|
17
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m171.04 KB[39m
|
|
18
|
+
[32mCJS[39m ⚡️ Build success in 116ms
|
|
19
19
|
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[
|
|
22
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[
|
|
20
|
+
[32mDTS[39m ⚡️ Build success in 11554ms
|
|
21
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m70.34 KB[39m
|
|
22
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m70.34 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @objectstack/objectql
|
|
2
2
|
|
|
3
|
+
## 3.0.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 437b0b8: feat(objectql): add utility functions, introspection types, and kernel factory
|
|
8
|
+
|
|
9
|
+
Upstream key functionality from downstream `@objectql/core` to enable its future deprecation:
|
|
10
|
+
|
|
11
|
+
- **Introspection types**: `IntrospectedSchema`, `IntrospectedTable`, `IntrospectedColumn`, `IntrospectedForeignKey`
|
|
12
|
+
- **Utility functions**: `toTitleCase()`, `convertIntrospectedSchemaToObjects()`
|
|
13
|
+
- **Kernel factory**: `createObjectQLKernel()` with `ObjectQLKernelOptions`
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [d738987]
|
|
16
|
+
- @objectstack/spec@3.0.4
|
|
17
|
+
- @objectstack/core@3.0.4
|
|
18
|
+
- @objectstack/types@3.0.4
|
|
19
|
+
|
|
3
20
|
## 3.0.3
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -8,16 +8,109 @@ The **Data Engine** for ObjectStack. It acts as a semantic layer between your ap
|
|
|
8
8
|
- **Schema Validation**: Enforces Zod schemas defined in `@objectstack/spec`.
|
|
9
9
|
- **Query Resolution**: Translates ObjectStack queries into driver-specific commands.
|
|
10
10
|
- **Driver Architecture**: Pluggable storage (Memory, MongoDB, SQL, etc.).
|
|
11
|
+
- **Schema Registry**: Centralized object/FQN management with multi-package ownership model.
|
|
12
|
+
- **Kernel Factory**: One-liner kernel bootstrap with `createObjectQLKernel()`.
|
|
13
|
+
- **Database Introspection**: Convert existing database schemas into ObjectStack metadata via `convertIntrospectedSchemaToObjects()`.
|
|
14
|
+
- **Metadata Facade**: Injectable `IMetadataService`-compatible wrapper over SchemaRegistry.
|
|
11
15
|
|
|
12
16
|
## Usage
|
|
13
17
|
|
|
18
|
+
### Querying Data
|
|
19
|
+
|
|
14
20
|
```typescript
|
|
15
21
|
import { ObjectQL } from '@objectstack/objectql';
|
|
16
22
|
|
|
17
|
-
// Querying data
|
|
18
23
|
const engine = kernel.getService('objectql');
|
|
19
24
|
const users = await engine.find('user', {
|
|
20
25
|
where: { role: 'admin' },
|
|
21
26
|
top: 10
|
|
22
27
|
});
|
|
23
28
|
```
|
|
29
|
+
|
|
30
|
+
### Kernel Factory
|
|
31
|
+
|
|
32
|
+
Create a fully wired ObjectKernel in one call:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { createObjectQLKernel } from '@objectstack/objectql';
|
|
36
|
+
|
|
37
|
+
const kernel = await createObjectQLKernel({
|
|
38
|
+
plugins: [myDriverPlugin, myAuthPlugin],
|
|
39
|
+
});
|
|
40
|
+
await kernel.bootstrap();
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Database Introspection
|
|
44
|
+
|
|
45
|
+
Convert existing database tables into ObjectStack object definitions:
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { convertIntrospectedSchemaToObjects } from '@objectstack/objectql';
|
|
49
|
+
|
|
50
|
+
const schema = await driver.introspectSchema();
|
|
51
|
+
const objects = convertIntrospectedSchemaToObjects(schema, {
|
|
52
|
+
excludeTables: ['migrations', '_prisma_migrations'],
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
for (const obj of objects) {
|
|
56
|
+
engine.registerObject(obj);
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Schema Registry
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { SchemaRegistry, computeFQN } from '@objectstack/objectql';
|
|
64
|
+
|
|
65
|
+
// Register an object under a namespace
|
|
66
|
+
SchemaRegistry.registerObject(taskDef, 'com.acme.todo', 'todo');
|
|
67
|
+
|
|
68
|
+
// Resolve FQN
|
|
69
|
+
computeFQN('todo', 'task'); // => 'todo__task'
|
|
70
|
+
computeFQN('base', 'user'); // => 'user' (reserved namespace)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Exported Components
|
|
74
|
+
|
|
75
|
+
| Export | Description |
|
|
76
|
+
| :--- | :--- |
|
|
77
|
+
| `ObjectQL` | Data engine implementing `IDataEngine` |
|
|
78
|
+
| `ObjectRepository` | Scoped repository bound to object + context |
|
|
79
|
+
| `ScopedContext` | Identity-scoped execution context with `object()` accessor |
|
|
80
|
+
| `SchemaRegistry` | Global schema registry (FQN, ownership, package management) |
|
|
81
|
+
| `MetadataFacade` | Async `IMetadataService`-compatible wrapper |
|
|
82
|
+
| `ObjectQLPlugin` | Kernel plugin that registers ObjectQL services |
|
|
83
|
+
| `ObjectStackProtocolImplementation` | Protocol implementation shim |
|
|
84
|
+
| `createObjectQLKernel()` | Async factory returning a pre-wired `ObjectKernel` |
|
|
85
|
+
| `toTitleCase()` | Convert `snake_case` to `Title Case` |
|
|
86
|
+
| `convertIntrospectedSchemaToObjects()` | DB schema → `ServiceObject[]` converter |
|
|
87
|
+
|
|
88
|
+
### Introspection Types
|
|
89
|
+
|
|
90
|
+
| Type | Description |
|
|
91
|
+
| :--- | :--- |
|
|
92
|
+
| `IntrospectedSchema` | Top-level schema with `tables` map |
|
|
93
|
+
| `IntrospectedTable` | Table metadata (columns, foreign keys, primary keys) |
|
|
94
|
+
| `IntrospectedColumn` | Column metadata (name, type, nullable, maxLength, …) |
|
|
95
|
+
| `IntrospectedForeignKey` | Foreign key relationship metadata |
|
|
96
|
+
|
|
97
|
+
## Migrating from `@objectql/core`
|
|
98
|
+
|
|
99
|
+
If you are migrating from the downstream `@objectql/core` package, see the
|
|
100
|
+
[Migration Guide](../../content/docs/guides/objectql-migration.mdx) for
|
|
101
|
+
step-by-step instructions.
|
|
102
|
+
|
|
103
|
+
**Quick summary:**
|
|
104
|
+
|
|
105
|
+
```diff
|
|
106
|
+
- import { ObjectQL, SchemaRegistry, ObjectRepository } from '@objectql/core';
|
|
107
|
+
- import { createObjectQLKernel } from '@objectql/core';
|
|
108
|
+
- import { toTitleCase, convertIntrospectedSchemaToObjects } from '@objectql/core';
|
|
109
|
+
+ import { ObjectQL, SchemaRegistry, ObjectRepository } from '@objectstack/objectql';
|
|
110
|
+
+ import { createObjectQLKernel } from '@objectstack/objectql';
|
|
111
|
+
+ import { toTitleCase, convertIntrospectedSchemaToObjects } from '@objectstack/objectql';
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
Apache-2.0 © ObjectStack
|
package/dist/index.d.mts
CHANGED
|
@@ -3,7 +3,7 @@ import * as _objectstack_spec_data from '@objectstack/spec/data';
|
|
|
3
3
|
import { ServiceObject, ObjectOwnership, HookContext, QueryAST, DataEngineQueryOptions, DataEngineInsertOptions, DataEngineUpdateOptions, DataEngineDeleteOptions, DataEngineCountOptions, DataEngineAggregateOptions } from '@objectstack/spec/data';
|
|
4
4
|
import { ObjectStackManifest, InstalledPackage, ExecutionContext } from '@objectstack/spec/kernel';
|
|
5
5
|
import { ObjectStackProtocol, MetadataCacheRequest, MetadataCacheResponse, BatchUpdateRequest, BatchUpdateResponse, UpdateManyDataRequest, DeleteManyDataRequest } from '@objectstack/spec/api';
|
|
6
|
-
import { IDataEngine, DriverInterface, Logger, Plugin, PluginContext } from '@objectstack/core';
|
|
6
|
+
import { IDataEngine, DriverInterface, Logger, Plugin, PluginContext, ObjectKernel } from '@objectstack/core';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* XState-inspired State Machine Protocol
|
|
@@ -1724,4 +1724,119 @@ declare class ObjectQLPlugin implements Plugin {
|
|
|
1724
1724
|
private loadMetadataFromService;
|
|
1725
1725
|
}
|
|
1726
1726
|
|
|
1727
|
-
|
|
1727
|
+
/**
|
|
1728
|
+
* Options for creating an ObjectQL Kernel.
|
|
1729
|
+
*/
|
|
1730
|
+
interface ObjectQLKernelOptions {
|
|
1731
|
+
/**
|
|
1732
|
+
* Additional plugins to register with the kernel.
|
|
1733
|
+
*/
|
|
1734
|
+
plugins?: Plugin[];
|
|
1735
|
+
}
|
|
1736
|
+
/**
|
|
1737
|
+
* Convenience factory for creating an ObjectQL-ready kernel.
|
|
1738
|
+
*
|
|
1739
|
+
* Creates an ObjectKernel pre-configured with the ObjectQLPlugin
|
|
1740
|
+
* (data engine, schema registry, protocol implementation) plus any
|
|
1741
|
+
* additional plugins provided.
|
|
1742
|
+
*
|
|
1743
|
+
* @example
|
|
1744
|
+
* ```typescript
|
|
1745
|
+
* import { createObjectQLKernel } from '@objectstack/objectql';
|
|
1746
|
+
*
|
|
1747
|
+
* const kernel = createObjectQLKernel({
|
|
1748
|
+
* plugins: [myDriverPlugin, myAuthPlugin],
|
|
1749
|
+
* });
|
|
1750
|
+
* await kernel.bootstrap();
|
|
1751
|
+
* ```
|
|
1752
|
+
*/
|
|
1753
|
+
declare function createObjectQLKernel(options?: ObjectQLKernelOptions): Promise<ObjectKernel>;
|
|
1754
|
+
|
|
1755
|
+
/**
|
|
1756
|
+
* Column metadata from database introspection.
|
|
1757
|
+
*/
|
|
1758
|
+
interface IntrospectedColumn {
|
|
1759
|
+
/** Column name */
|
|
1760
|
+
name: string;
|
|
1761
|
+
/** Native database type (e.g., 'varchar', 'integer', 'timestamp') */
|
|
1762
|
+
type: string;
|
|
1763
|
+
/** Whether the column is nullable */
|
|
1764
|
+
nullable: boolean;
|
|
1765
|
+
/** Default value if any */
|
|
1766
|
+
defaultValue?: unknown;
|
|
1767
|
+
/** Whether this is a primary key */
|
|
1768
|
+
isPrimary?: boolean;
|
|
1769
|
+
/** Whether this column has a unique constraint */
|
|
1770
|
+
isUnique?: boolean;
|
|
1771
|
+
/** Maximum length for string types */
|
|
1772
|
+
maxLength?: number;
|
|
1773
|
+
}
|
|
1774
|
+
/**
|
|
1775
|
+
* Foreign key relationship metadata.
|
|
1776
|
+
*/
|
|
1777
|
+
interface IntrospectedForeignKey {
|
|
1778
|
+
/** Column name in the source table */
|
|
1779
|
+
columnName: string;
|
|
1780
|
+
/** Referenced table name */
|
|
1781
|
+
referencedTable: string;
|
|
1782
|
+
/** Referenced column name */
|
|
1783
|
+
referencedColumn: string;
|
|
1784
|
+
/** Constraint name */
|
|
1785
|
+
constraintName?: string;
|
|
1786
|
+
}
|
|
1787
|
+
/**
|
|
1788
|
+
* Table metadata from database introspection.
|
|
1789
|
+
*/
|
|
1790
|
+
interface IntrospectedTable {
|
|
1791
|
+
/** Table name */
|
|
1792
|
+
name: string;
|
|
1793
|
+
/** List of columns */
|
|
1794
|
+
columns: IntrospectedColumn[];
|
|
1795
|
+
/** List of foreign key relationships */
|
|
1796
|
+
foreignKeys: IntrospectedForeignKey[];
|
|
1797
|
+
/** Primary key columns */
|
|
1798
|
+
primaryKeys: string[];
|
|
1799
|
+
}
|
|
1800
|
+
/**
|
|
1801
|
+
* Complete database schema introspection result.
|
|
1802
|
+
*/
|
|
1803
|
+
interface IntrospectedSchema {
|
|
1804
|
+
/** Map of table name to table metadata */
|
|
1805
|
+
tables: Record<string, IntrospectedTable>;
|
|
1806
|
+
}
|
|
1807
|
+
/**
|
|
1808
|
+
* Convert a snake_case or plain string to Title Case.
|
|
1809
|
+
*
|
|
1810
|
+
* @example
|
|
1811
|
+
* toTitleCase('first_name') // => 'First Name'
|
|
1812
|
+
* toTitleCase('project_task') // => 'Project Task'
|
|
1813
|
+
*/
|
|
1814
|
+
declare function toTitleCase(str: string): string;
|
|
1815
|
+
/**
|
|
1816
|
+
* Convert an introspected database schema to ObjectStack object definitions.
|
|
1817
|
+
*
|
|
1818
|
+
* This allows using existing database tables without manually defining metadata.
|
|
1819
|
+
*
|
|
1820
|
+
* @param introspectedSchema - The schema returned from driver.introspectSchema()
|
|
1821
|
+
* @param options - Optional filtering / conversion settings
|
|
1822
|
+
* @returns Array of ServiceObject definitions that can be registered with ObjectQL
|
|
1823
|
+
*
|
|
1824
|
+
* @example
|
|
1825
|
+
* ```typescript
|
|
1826
|
+
* const schema = await driver.introspectSchema();
|
|
1827
|
+
* const objects = convertIntrospectedSchemaToObjects(schema);
|
|
1828
|
+
* for (const obj of objects) {
|
|
1829
|
+
* engine.registerObject(obj);
|
|
1830
|
+
* }
|
|
1831
|
+
* ```
|
|
1832
|
+
*/
|
|
1833
|
+
declare function convertIntrospectedSchemaToObjects(introspectedSchema: IntrospectedSchema, options?: {
|
|
1834
|
+
/** Tables to exclude from conversion */
|
|
1835
|
+
excludeTables?: string[];
|
|
1836
|
+
/** Tables to include (if specified, only these will be converted) */
|
|
1837
|
+
includeTables?: string[];
|
|
1838
|
+
/** Whether to skip system columns like id, created_at, updated_at (default: true) */
|
|
1839
|
+
skipSystemColumns?: boolean;
|
|
1840
|
+
}): ServiceObject[];
|
|
1841
|
+
|
|
1842
|
+
export { DEFAULT_EXTENDER_PRIORITY, DEFAULT_OWNER_PRIORITY, type EngineMiddleware, type HookEntry, type HookHandler, type IntrospectedColumn, type IntrospectedForeignKey, type IntrospectedSchema, type IntrospectedTable, MetadataFacade, type ObjectContributor, ObjectQL, type ObjectQLHostContext, type ObjectQLKernelOptions, ObjectQLPlugin, ObjectRepository, ObjectStackProtocolImplementation, type OperationContext, RESERVED_NAMESPACES, SchemaRegistry, ScopedContext, computeFQN, convertIntrospectedSchemaToObjects, createObjectQLKernel, parseFQN, toTitleCase };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as _objectstack_spec_data from '@objectstack/spec/data';
|
|
|
3
3
|
import { ServiceObject, ObjectOwnership, HookContext, QueryAST, DataEngineQueryOptions, DataEngineInsertOptions, DataEngineUpdateOptions, DataEngineDeleteOptions, DataEngineCountOptions, DataEngineAggregateOptions } from '@objectstack/spec/data';
|
|
4
4
|
import { ObjectStackManifest, InstalledPackage, ExecutionContext } from '@objectstack/spec/kernel';
|
|
5
5
|
import { ObjectStackProtocol, MetadataCacheRequest, MetadataCacheResponse, BatchUpdateRequest, BatchUpdateResponse, UpdateManyDataRequest, DeleteManyDataRequest } from '@objectstack/spec/api';
|
|
6
|
-
import { IDataEngine, DriverInterface, Logger, Plugin, PluginContext } from '@objectstack/core';
|
|
6
|
+
import { IDataEngine, DriverInterface, Logger, Plugin, PluginContext, ObjectKernel } from '@objectstack/core';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* XState-inspired State Machine Protocol
|
|
@@ -1724,4 +1724,119 @@ declare class ObjectQLPlugin implements Plugin {
|
|
|
1724
1724
|
private loadMetadataFromService;
|
|
1725
1725
|
}
|
|
1726
1726
|
|
|
1727
|
-
|
|
1727
|
+
/**
|
|
1728
|
+
* Options for creating an ObjectQL Kernel.
|
|
1729
|
+
*/
|
|
1730
|
+
interface ObjectQLKernelOptions {
|
|
1731
|
+
/**
|
|
1732
|
+
* Additional plugins to register with the kernel.
|
|
1733
|
+
*/
|
|
1734
|
+
plugins?: Plugin[];
|
|
1735
|
+
}
|
|
1736
|
+
/**
|
|
1737
|
+
* Convenience factory for creating an ObjectQL-ready kernel.
|
|
1738
|
+
*
|
|
1739
|
+
* Creates an ObjectKernel pre-configured with the ObjectQLPlugin
|
|
1740
|
+
* (data engine, schema registry, protocol implementation) plus any
|
|
1741
|
+
* additional plugins provided.
|
|
1742
|
+
*
|
|
1743
|
+
* @example
|
|
1744
|
+
* ```typescript
|
|
1745
|
+
* import { createObjectQLKernel } from '@objectstack/objectql';
|
|
1746
|
+
*
|
|
1747
|
+
* const kernel = createObjectQLKernel({
|
|
1748
|
+
* plugins: [myDriverPlugin, myAuthPlugin],
|
|
1749
|
+
* });
|
|
1750
|
+
* await kernel.bootstrap();
|
|
1751
|
+
* ```
|
|
1752
|
+
*/
|
|
1753
|
+
declare function createObjectQLKernel(options?: ObjectQLKernelOptions): Promise<ObjectKernel>;
|
|
1754
|
+
|
|
1755
|
+
/**
|
|
1756
|
+
* Column metadata from database introspection.
|
|
1757
|
+
*/
|
|
1758
|
+
interface IntrospectedColumn {
|
|
1759
|
+
/** Column name */
|
|
1760
|
+
name: string;
|
|
1761
|
+
/** Native database type (e.g., 'varchar', 'integer', 'timestamp') */
|
|
1762
|
+
type: string;
|
|
1763
|
+
/** Whether the column is nullable */
|
|
1764
|
+
nullable: boolean;
|
|
1765
|
+
/** Default value if any */
|
|
1766
|
+
defaultValue?: unknown;
|
|
1767
|
+
/** Whether this is a primary key */
|
|
1768
|
+
isPrimary?: boolean;
|
|
1769
|
+
/** Whether this column has a unique constraint */
|
|
1770
|
+
isUnique?: boolean;
|
|
1771
|
+
/** Maximum length for string types */
|
|
1772
|
+
maxLength?: number;
|
|
1773
|
+
}
|
|
1774
|
+
/**
|
|
1775
|
+
* Foreign key relationship metadata.
|
|
1776
|
+
*/
|
|
1777
|
+
interface IntrospectedForeignKey {
|
|
1778
|
+
/** Column name in the source table */
|
|
1779
|
+
columnName: string;
|
|
1780
|
+
/** Referenced table name */
|
|
1781
|
+
referencedTable: string;
|
|
1782
|
+
/** Referenced column name */
|
|
1783
|
+
referencedColumn: string;
|
|
1784
|
+
/** Constraint name */
|
|
1785
|
+
constraintName?: string;
|
|
1786
|
+
}
|
|
1787
|
+
/**
|
|
1788
|
+
* Table metadata from database introspection.
|
|
1789
|
+
*/
|
|
1790
|
+
interface IntrospectedTable {
|
|
1791
|
+
/** Table name */
|
|
1792
|
+
name: string;
|
|
1793
|
+
/** List of columns */
|
|
1794
|
+
columns: IntrospectedColumn[];
|
|
1795
|
+
/** List of foreign key relationships */
|
|
1796
|
+
foreignKeys: IntrospectedForeignKey[];
|
|
1797
|
+
/** Primary key columns */
|
|
1798
|
+
primaryKeys: string[];
|
|
1799
|
+
}
|
|
1800
|
+
/**
|
|
1801
|
+
* Complete database schema introspection result.
|
|
1802
|
+
*/
|
|
1803
|
+
interface IntrospectedSchema {
|
|
1804
|
+
/** Map of table name to table metadata */
|
|
1805
|
+
tables: Record<string, IntrospectedTable>;
|
|
1806
|
+
}
|
|
1807
|
+
/**
|
|
1808
|
+
* Convert a snake_case or plain string to Title Case.
|
|
1809
|
+
*
|
|
1810
|
+
* @example
|
|
1811
|
+
* toTitleCase('first_name') // => 'First Name'
|
|
1812
|
+
* toTitleCase('project_task') // => 'Project Task'
|
|
1813
|
+
*/
|
|
1814
|
+
declare function toTitleCase(str: string): string;
|
|
1815
|
+
/**
|
|
1816
|
+
* Convert an introspected database schema to ObjectStack object definitions.
|
|
1817
|
+
*
|
|
1818
|
+
* This allows using existing database tables without manually defining metadata.
|
|
1819
|
+
*
|
|
1820
|
+
* @param introspectedSchema - The schema returned from driver.introspectSchema()
|
|
1821
|
+
* @param options - Optional filtering / conversion settings
|
|
1822
|
+
* @returns Array of ServiceObject definitions that can be registered with ObjectQL
|
|
1823
|
+
*
|
|
1824
|
+
* @example
|
|
1825
|
+
* ```typescript
|
|
1826
|
+
* const schema = await driver.introspectSchema();
|
|
1827
|
+
* const objects = convertIntrospectedSchemaToObjects(schema);
|
|
1828
|
+
* for (const obj of objects) {
|
|
1829
|
+
* engine.registerObject(obj);
|
|
1830
|
+
* }
|
|
1831
|
+
* ```
|
|
1832
|
+
*/
|
|
1833
|
+
declare function convertIntrospectedSchemaToObjects(introspectedSchema: IntrospectedSchema, options?: {
|
|
1834
|
+
/** Tables to exclude from conversion */
|
|
1835
|
+
excludeTables?: string[];
|
|
1836
|
+
/** Tables to include (if specified, only these will be converted) */
|
|
1837
|
+
includeTables?: string[];
|
|
1838
|
+
/** Whether to skip system columns like id, created_at, updated_at (default: true) */
|
|
1839
|
+
skipSystemColumns?: boolean;
|
|
1840
|
+
}): ServiceObject[];
|
|
1841
|
+
|
|
1842
|
+
export { DEFAULT_EXTENDER_PRIORITY, DEFAULT_OWNER_PRIORITY, type EngineMiddleware, type HookEntry, type HookHandler, type IntrospectedColumn, type IntrospectedForeignKey, type IntrospectedSchema, type IntrospectedTable, MetadataFacade, type ObjectContributor, ObjectQL, type ObjectQLHostContext, type ObjectQLKernelOptions, ObjectQLPlugin, ObjectRepository, ObjectStackProtocolImplementation, type OperationContext, RESERVED_NAMESPACES, SchemaRegistry, ScopedContext, computeFQN, convertIntrospectedSchemaToObjects, createObjectQLKernel, parseFQN, toTitleCase };
|
package/dist/index.js
CHANGED
|
@@ -31,7 +31,10 @@ __export(index_exports, {
|
|
|
31
31
|
SchemaRegistry: () => SchemaRegistry,
|
|
32
32
|
ScopedContext: () => ScopedContext,
|
|
33
33
|
computeFQN: () => computeFQN,
|
|
34
|
-
|
|
34
|
+
convertIntrospectedSchemaToObjects: () => convertIntrospectedSchemaToObjects,
|
|
35
|
+
createObjectQLKernel: () => createObjectQLKernel,
|
|
36
|
+
parseFQN: () => parseFQN,
|
|
37
|
+
toTitleCase: () => toTitleCase
|
|
35
38
|
});
|
|
36
39
|
module.exports = __toCommonJS(index_exports);
|
|
37
40
|
|
|
@@ -2460,6 +2463,103 @@ var ObjectQLPlugin = class {
|
|
|
2460
2463
|
}
|
|
2461
2464
|
}
|
|
2462
2465
|
};
|
|
2466
|
+
|
|
2467
|
+
// src/kernel-factory.ts
|
|
2468
|
+
var import_core2 = require("@objectstack/core");
|
|
2469
|
+
async function createObjectQLKernel(options = {}) {
|
|
2470
|
+
const kernel = new import_core2.ObjectKernel();
|
|
2471
|
+
await kernel.use(new ObjectQLPlugin());
|
|
2472
|
+
if (options.plugins) {
|
|
2473
|
+
for (const plugin of options.plugins) {
|
|
2474
|
+
await kernel.use(plugin);
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
return kernel;
|
|
2478
|
+
}
|
|
2479
|
+
|
|
2480
|
+
// src/util.ts
|
|
2481
|
+
function toTitleCase(str) {
|
|
2482
|
+
return str.replace(/_/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
|
|
2483
|
+
}
|
|
2484
|
+
function mapDatabaseTypeToFieldType(dbType) {
|
|
2485
|
+
const type = dbType.toLowerCase();
|
|
2486
|
+
if (type.includes("char") || type.includes("varchar") || type.includes("text")) {
|
|
2487
|
+
if (type.includes("text")) return "textarea";
|
|
2488
|
+
return "text";
|
|
2489
|
+
}
|
|
2490
|
+
if (type.includes("int") || type === "integer" || type === "bigint" || type === "smallint") {
|
|
2491
|
+
return "number";
|
|
2492
|
+
}
|
|
2493
|
+
if (type.includes("float") || type.includes("double") || type.includes("decimal") || type.includes("numeric") || type === "real") {
|
|
2494
|
+
return "number";
|
|
2495
|
+
}
|
|
2496
|
+
if (type.includes("bool")) {
|
|
2497
|
+
return "boolean";
|
|
2498
|
+
}
|
|
2499
|
+
if (type.includes("timestamp") || type === "datetime") {
|
|
2500
|
+
return "datetime";
|
|
2501
|
+
}
|
|
2502
|
+
if (type === "date") {
|
|
2503
|
+
return "date";
|
|
2504
|
+
}
|
|
2505
|
+
if (type === "time") {
|
|
2506
|
+
return "time";
|
|
2507
|
+
}
|
|
2508
|
+
if (type === "json" || type === "jsonb") {
|
|
2509
|
+
return "json";
|
|
2510
|
+
}
|
|
2511
|
+
return "text";
|
|
2512
|
+
}
|
|
2513
|
+
function convertIntrospectedSchemaToObjects(introspectedSchema, options) {
|
|
2514
|
+
const objects = [];
|
|
2515
|
+
const excludeTables = options?.excludeTables || [];
|
|
2516
|
+
const includeTables = options?.includeTables;
|
|
2517
|
+
const skipSystemColumns = options?.skipSystemColumns !== false;
|
|
2518
|
+
for (const [tableName, table] of Object.entries(introspectedSchema.tables)) {
|
|
2519
|
+
if (excludeTables.includes(tableName)) continue;
|
|
2520
|
+
if (includeTables && !includeTables.includes(tableName)) continue;
|
|
2521
|
+
const fields = {};
|
|
2522
|
+
for (const column of table.columns) {
|
|
2523
|
+
if (skipSystemColumns && ["id", "created_at", "updated_at"].includes(column.name)) {
|
|
2524
|
+
continue;
|
|
2525
|
+
}
|
|
2526
|
+
const foreignKey = table.foreignKeys.find((fk) => fk.columnName === column.name);
|
|
2527
|
+
if (foreignKey) {
|
|
2528
|
+
fields[column.name] = {
|
|
2529
|
+
name: column.name,
|
|
2530
|
+
type: "lookup",
|
|
2531
|
+
reference: foreignKey.referencedTable,
|
|
2532
|
+
label: toTitleCase(column.name),
|
|
2533
|
+
required: !column.nullable
|
|
2534
|
+
};
|
|
2535
|
+
} else {
|
|
2536
|
+
const fieldType = mapDatabaseTypeToFieldType(column.type);
|
|
2537
|
+
const field = {
|
|
2538
|
+
name: column.name,
|
|
2539
|
+
type: fieldType,
|
|
2540
|
+
label: toTitleCase(column.name),
|
|
2541
|
+
required: !column.nullable
|
|
2542
|
+
};
|
|
2543
|
+
if (column.isUnique) {
|
|
2544
|
+
field.unique = true;
|
|
2545
|
+
}
|
|
2546
|
+
if (column.maxLength && (fieldType === "text" || fieldType === "textarea")) {
|
|
2547
|
+
field.maxLength = column.maxLength;
|
|
2548
|
+
}
|
|
2549
|
+
if (column.defaultValue != null) {
|
|
2550
|
+
field.defaultValue = column.defaultValue;
|
|
2551
|
+
}
|
|
2552
|
+
fields[column.name] = field;
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
objects.push({
|
|
2556
|
+
name: tableName,
|
|
2557
|
+
label: toTitleCase(tableName),
|
|
2558
|
+
fields
|
|
2559
|
+
});
|
|
2560
|
+
}
|
|
2561
|
+
return objects;
|
|
2562
|
+
}
|
|
2463
2563
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2464
2564
|
0 && (module.exports = {
|
|
2465
2565
|
DEFAULT_EXTENDER_PRIORITY,
|
|
@@ -2473,6 +2573,9 @@ var ObjectQLPlugin = class {
|
|
|
2473
2573
|
SchemaRegistry,
|
|
2474
2574
|
ScopedContext,
|
|
2475
2575
|
computeFQN,
|
|
2476
|
-
|
|
2576
|
+
convertIntrospectedSchemaToObjects,
|
|
2577
|
+
createObjectQLKernel,
|
|
2578
|
+
parseFQN,
|
|
2579
|
+
toTitleCase
|
|
2477
2580
|
});
|
|
2478
2581
|
//# sourceMappingURL=index.js.map
|