@harperfast/template-react-studio 0.8.7 → 0.9.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/AGENTS.md ADDED
@@ -0,0 +1,16 @@
1
+ # HarperDB Agent Skills
2
+
3
+ This repository contains "skills" that guide AI agents in developing Harper applications.
4
+
5
+ ## Available Skills
6
+
7
+ - [Adding Tables](skills/adding-tables.md): Learn how to define schemas and enable automatic REST APIs for your database tables.
8
+ - [Automatic REST APIs](skills/automatic-rest-apis.md): Details on the CRUD endpoints automatically generated for exported tables.
9
+ - [Querying REST APIs](skills/querying-rest-apis.md): How to use filters, operators, sorting, and pagination in REST requests.
10
+ - [Custom Resources](skills/custom-resources.md): How to define custom REST endpoints using JavaScript or TypeScript (Note: Paths are case-sensitive).
11
+ - [Extending Table Resources](skills/extending-tables.md): Adding custom logic to automatically generated table resources.
12
+ - [Defining Relationships](skills/defining-relationships.md): Using the `@relationship` directive to link tables.
13
+ - [Real-time Applications](skills/real-time-apps.md): Implementing WebSockets and Pub/Sub for live data updates.
14
+ - [TypeScript Type Stripping](skills/typescript-type-stripping.md): Using TypeScript directly without build tools via Node.js Type Stripping.
15
+ - [Handling Binary Data](skills/handling-binary-data.md): How to store and serve binary data like images or MP3s.
16
+ - [Checking Authentication](skills/checking-authentication.md): How to use `this.getCurrentUser()` to verify user identity and roles.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harperfast/template-react-studio",
3
- "version": "0.8.7",
3
+ "version": "0.9.0",
4
4
  "type": "module",
5
5
  "repository": "github:HarperFast/create-harper",
6
6
  "scripts": {},
@@ -0,0 +1,32 @@
1
+ # Adding Tables to HarperDB
2
+
3
+ To add tables to a Harper database, follow these guidelines:
4
+
5
+ 1. **Dedicated Schema Files**: Prefer having a dedicated schema `.graphql` file for each table. Check the `config.yaml` file under `graphqlSchema.files` to see how it's configured. It typically accepts wildcards (e.g., `schemas/*.graphql`), but may be configured to point at a single file.
6
+
7
+ 2. **Directives**: All available directives for defining your schema are defined in `node_modules/harperdb/schema.graphql`. Common directives include `@table`, `@export`, `@primaryKey`, `@indexed`, and `@relationship`.
8
+
9
+ 3. **Defining Relationships**: You can link tables together using the `@relationship` directive. For more details, see the [Defining Relationships](defining-relationships.md) skill.
10
+
11
+ 4. **Automatic REST APIs**: If you add `@table @export` to a schema type, HarperDB automatically sets up REST APIs for basic CRUD operations against that table. For a detailed list of available endpoints and how to use them, see the [Automatic REST APIs](automatic-rest-apis.md) skill.
12
+
13
+ - `GET /{TableName}`: Describes the schema itself.
14
+ - `GET /{TableName}/`: Lists all records (supports filtering, sorting, and pagination via query parameters). See the [Querying REST APIs](querying-rest-apis.md) skill for details.
15
+ - `GET /{TableName}/{id}`: Retrieves a single record by its ID.
16
+ - `POST /{TableName}/`: Creates a new record.
17
+ - `PUT /{TableName}/{id}`: Updates an existing record.
18
+ - `PATCH /{TableName}/{id}`: Performs a partial update on a record.
19
+ - `DELETE /{TableName}/`: Deletes all records or filtered records.
20
+ - `DELETE /{TableName}/{id}`: Deletes a single record by its ID.
21
+
22
+ ### Example
23
+
24
+ In `schemas/ExampleTable.graphql`:
25
+
26
+ ```graphql
27
+ type ExampleTable @table @export {
28
+ id: ID @primaryKey
29
+ name: String
30
+ email: String @indexed
31
+ }
32
+ ```
@@ -0,0 +1,41 @@
1
+ # Automatic REST APIs in HarperDB
2
+
3
+ When you define a GraphQL type with the `@table` and `@export` directives, HarperDB automatically generates a fully-functional REST API for that table. This allows for immediate CRUD (Create, Read, Update, Delete) operations without writing any additional code.
4
+
5
+ ## Enabling REST APIs
6
+
7
+ To enable the automatic REST API for a table, ensure your GraphQL schema includes the `@export` directive:
8
+
9
+ ```graphql
10
+ type MyTable @table @export {
11
+ id: ID @primaryKey
12
+ # ... other fields
13
+ }
14
+ ```
15
+
16
+ ## Available Endpoints
17
+
18
+ The following endpoints are automatically created for a table named `TableName` (Note: Paths are **case-sensitive**, so `GET /TableName/` is valid while `GET /tablename/` is not):
19
+
20
+ - **Describe Schema**: `GET /{TableName}`
21
+ Returns the schema definition and metadata for the table.
22
+ - **List Records**: `GET /{TableName}/`
23
+ Lists all records in the table. This endpoint supports advanced filtering, sorting, and pagination. For more details, see the [Querying REST APIs](querying-rest-apis.md) skill.
24
+ - **Get Single Record**: `GET /{TableName}/{id}`
25
+ Retrieves a single record by its primary key (`id`).
26
+ - **Create Record**: `POST /{TableName}/`
27
+ Creates a new record. The request body should be a JSON object containing the record data.
28
+ - **Update Record (Full)**: `PUT /{TableName}/{id}`
29
+ Replaces the entire record at the specified `id` with the provided JSON data.
30
+ - **Update Record (Partial)**: `PATCH /{TableName}/{id}`
31
+ Updates only the specified fields of the record at the given `id`.
32
+ - **Delete All/Filtered Records**: `DELETE /{TableName}/`
33
+ Deletes all records in the table, or a subset of records if filtering parameters are provided.
34
+ - **Delete Single Record**: `DELETE /{TableName}/{id}`
35
+ Deletes the record with the specified `id`.
36
+
37
+ ## Filtering and Querying
38
+
39
+ The `GET /{TableName}/` and `DELETE /{TableName}/` endpoints can be filtered using query parameters. While basic equality filters are straightforward, HarperDB supports a rich set of operators, sorting, and pagination.
40
+
41
+ For a comprehensive guide on advanced querying, see the [Querying REST APIs](querying-rest-apis.md) skill.
@@ -0,0 +1,52 @@
1
+ # Checking Authentication in HarperDB
2
+
3
+ Custom resources and table resource overrides often need to restrict access based on the current user's identity or role. HarperDB provides the `this.getCurrentUser()` method within resource classes to access information about the authenticated user making the request.
4
+
5
+ ## Using `this.getCurrentUser()`
6
+
7
+ The `this.getCurrentUser()` method returns an object containing details about the authenticated user, such as their username and role. If the request is unauthenticated, it may return `null` or `undefined`.
8
+
9
+ ### Example: Role-Based Access Control
10
+
11
+ You can check the user's role to determine if they have permission to perform a specific action.
12
+
13
+ ```typescript
14
+ import { RequestTargetOrId, Resource } from 'harperdb';
15
+
16
+ export class MyResource extends Resource {
17
+ async post(target: RequestTargetOrId, record: any) {
18
+ const user = this.getCurrentUser();
19
+
20
+ // Check if the user has the 'super_user' role
21
+ if (user?.role?.role !== 'super_user') {
22
+ throw {
23
+ message: 'Only super users are allowed to make changes',
24
+ statusCode: 403,
25
+ };
26
+ }
27
+
28
+ return super.post(target, record);
29
+ }
30
+ }
31
+ ```
32
+
33
+ ## Handling Unauthenticated Requests
34
+
35
+ Always ensure you handle cases where `this.getCurrentUser()` returns `null`, especially if your resource is accessible to unauthenticated users.
36
+
37
+ ```typescript
38
+ const user = this.getCurrentUser();
39
+ if (!user) {
40
+ throw {
41
+ message: 'Authentication required',
42
+ statusCode: 401,
43
+ };
44
+ }
45
+ ```
46
+
47
+ ## User Object Structure
48
+
49
+ The object returned by `this.getCurrentUser()` typically includes:
50
+
51
+ - `username`: The username of the authenticated user.
52
+ - `role`: An object containing role information, including the `role` name itself (e.g., `user.role.role`).
@@ -0,0 +1,82 @@
1
+ # Custom Resources in HarperDB
2
+
3
+ Custom Resources allow you to define your own REST endpoints with custom logic by writing JavaScript or TypeScript code. This is useful when the automatic CRUD operations provided by `@table @export` are not enough.
4
+
5
+ HarperDB supports [TypeScript Type Stripping](typescript-type-stripping.md), allowing you to use TypeScript directly without additional build tools on supported Node.js versions.
6
+
7
+ ## Defining a Custom Resource
8
+
9
+ To create a custom resource:
10
+
11
+ 1. Create a `.ts` (or `.js`) file in the directory specified by `jsResource` in `config.yaml` (usually `resources/`).
12
+ 2. Export a class that extends the `Resource` class from the `harperdb` module.
13
+
14
+ ### Example: `resources/greeting.ts`
15
+
16
+ ```typescript
17
+ import { type RecordObject, type RequestTargetOrId, Resource } from 'harperdb';
18
+
19
+ interface GreetingRecord {
20
+ greeting: string;
21
+ }
22
+
23
+ export class Greeting extends Resource<GreetingRecord> {
24
+ // Set to false if you want HarperDB to manage the instance lifecycle
25
+ static loadAsInstance = false;
26
+
27
+ async get(target?: RequestTargetOrId): Promise<GreetingRecord> {
28
+ return { greeting: 'Hello from a custom GET endpoint!' };
29
+ }
30
+
31
+ async post(
32
+ target: RequestTargetOrId,
33
+ newRecord: Partial<GreetingRecord & RecordObject>,
34
+ ): Promise<GreetingRecord> {
35
+ // Custom logic for handling POST requests
36
+ return { greeting: `Hello, ${newRecord.greeting || 'stranger'}!` };
37
+ }
38
+ }
39
+ ```
40
+
41
+ ## Supported HTTP Methods
42
+
43
+ You can implement any of the following methods in your resource class to handle the corresponding HTTP requests:
44
+
45
+ - `get(target?: RequestTargetOrId)`
46
+ - `post(target: RequestTargetOrId, body: any)`
47
+ - `put(target: RequestTargetOrId, body: any)`
48
+ - `patch(target: RequestTargetOrId, body: any)`
49
+ - `delete(target: RequestTargetOrId)`
50
+
51
+ The `target` parameter typically contains the ID or sub-path from the URL.
52
+
53
+ ## Accessing Tables
54
+
55
+ Within your custom resource, you can easily access your database tables using the `tables` object:
56
+
57
+ ```typescript
58
+ import { Resource, tables } from 'harperdb';
59
+
60
+ export class MyCustomResource extends Resource {
61
+ async get() {
62
+ // Query a table
63
+ const results = await tables.ExamplePeople.list();
64
+ return results;
65
+ }
66
+ }
67
+ ```
68
+
69
+ ## Configuration
70
+
71
+ Ensure your `config.yaml` is configured to load your resources:
72
+
73
+ ```yaml
74
+ jsResource:
75
+ files: 'resources/*.ts'
76
+ ```
77
+
78
+ Once defined and configured, your resource will be available at a REST endpoint matching the class name exactly.
79
+
80
+ ### Case Sensitivity
81
+
82
+ Paths in HarperDB are **case-sensitive**. A resource class named `MyResource` will be accessible only at `/MyResource/`, not `/myresource/`.
@@ -0,0 +1,71 @@
1
+ # Defining Relationships in HarperDB
2
+
3
+ HarperDB allows you to define relationships between tables using the `@relationship` directive in your GraphQL schema. This enables powerful features like automatic joins when querying through REST APIs.
4
+
5
+ ## The `@relationship` Directive
6
+
7
+ The `@relationship` directive is applied to a field in your GraphQL type and takes two optional arguments:
8
+
9
+ - `from`: The field in the _current_ table that holds the foreign key.
10
+ - `to`: The field in the _related_ table that holds the foreign key.
11
+
12
+ ## Relationship Types
13
+
14
+ ### One-to-One and Many-to-One
15
+
16
+ To define a relationship where the current table holds the foreign key, use the `from` argument.
17
+
18
+ ```graphql
19
+ type Author @table @export {
20
+ id: ID @primaryKey
21
+ name: String
22
+ }
23
+
24
+ type Book @table @export {
25
+ id: ID @primaryKey
26
+ title: String
27
+ authorId: ID
28
+ # This field resolves to an Author object using authorId
29
+ author: Author @relationship(from: "authorId")
30
+ }
31
+ ```
32
+
33
+ ### One-to-Many and Many-to-Many
34
+
35
+ To define a relationship where the _related_ table holds the foreign key, use the `to` argument. The field type should be an array.
36
+
37
+ ```graphql
38
+ type Author @table @export {
39
+ id: ID @primaryKey
40
+ name: String
41
+ # This field resolves to an array of Books that have this author's ID in their authorId field
42
+ books: [Book] @relationship(to: "authorId")
43
+ }
44
+
45
+ type Book @table @export {
46
+ id: ID @primaryKey
47
+ title: String
48
+ authorId: ID
49
+ }
50
+ ```
51
+
52
+ ## Querying Relationships
53
+
54
+ Once relationships are defined, you can use them in your REST API queries using dot syntax.
55
+
56
+ Example:
57
+ `GET /Book/?author.name=Harper`
58
+
59
+ This will automatically perform a join and return all books whose author's name is "Harper".
60
+
61
+ You can also use the `select()` operator to include related data in the response:
62
+
63
+ `GET /Author/?select(name,books(title))`
64
+
65
+ This returns authors with their names and a list of their books (only the titles).
66
+
67
+ ## Benefits of `@relationship`
68
+
69
+ - **Simplified Queries**: No need for complex manual joins in your code.
70
+ - **Efficient Data Fetching**: HarperDB optimizes relationship lookups.
71
+ - **Improved API Discoverability**: Related data structures are clearly defined in your schema.
@@ -0,0 +1,56 @@
1
+ # Extending Table Resources in HarperDB
2
+
3
+ In HarperDB, when you define a table in GraphQL and export it, you can extend the automatically generated resource class to add custom logic, validation, or hooks to standard CRUD operations.
4
+
5
+ ## How to Extend a Table Resource
6
+
7
+ 1. Identify the table you want to extend (e.g., `ExamplePeople`).
8
+ 2. Create a TypeScript file in your `resources/` folder.
9
+ 3. Export a class that extends `tables.YourTableName`.
10
+ 4. Override the desired methods (e.g., `post`, `get`, `put`, `patch`, `delete`).
11
+
12
+ ### Example: `resources/examplePeople.ts`
13
+
14
+ ```typescript
15
+ import { type RequestTargetOrId, tables } from 'harperdb';
16
+
17
+ export interface ExamplePerson {
18
+ id: string;
19
+ name: string;
20
+ tag: string;
21
+ }
22
+
23
+ // Extend the automatically generated table resource
24
+ export class ExamplePeople extends tables.ExamplePeople<ExamplePerson> {
25
+ // Override the custom POST handler
26
+ async post(target: RequestTargetOrId, newRecord: Omit<ExamplePerson, 'id'>) {
27
+ // Add custom validation or transformation logic
28
+ if (!newRecord.name) {
29
+ throw new Error('Name is required');
30
+ }
31
+
32
+ console.log(`Adding new person: ${newRecord.name}`);
33
+
34
+ // Call the super method to perform the actual insertion
35
+ return super.post(target, newRecord);
36
+ }
37
+
38
+ // Override the custom GET handler
39
+ async get(target: RequestTargetOrId) {
40
+ const record = await super.get(target);
41
+ // Modify the record before returning if necessary
42
+ return record;
43
+ }
44
+ }
45
+ ```
46
+
47
+ ## Why Extend Tables?
48
+
49
+ - **Validation**: Ensure data meets specific criteria before it's saved to the database.
50
+ - **Side Effects**: Send an email, trigger a webhook, or log an event when a record is created or updated.
51
+ - **Data Transformation**: Format or enrich data before it's returned to the client.
52
+ - **Access Control**: Add custom logic to determine if a user has permission to access or modify a specific record.
53
+
54
+ ## Important Note
55
+
56
+ When you extend a table resource, HarperDB uses your custom class for all REST API interactions with that table. Make sure to call `super[method]` if you still want the default behavior to occur after your custom logic.
@@ -0,0 +1,65 @@
1
+ # Handling Binary Data in HarperDB
2
+
3
+ When working with binary data (such as images or audio files) in HarperDB, you often receive this data as base64-encoded strings through JSON REST APIs. To store this data efficiently in a `Blob` field, you should convert it to a `Buffer`.
4
+
5
+ ## Storing Base64 Strings as Buffers
6
+
7
+ In a custom resource or a table resource override, you can intercept the incoming record and convert base64 strings to buffers before saving them to the database.
8
+
9
+ ### Example
10
+
11
+ Suppose you have a table with a `Blob` field named `data`. You can use `Buffer.from(string, 'base64')` to perform the conversion.
12
+
13
+ ```typescript
14
+ import { RequestTargetOrId, Resource } from 'harperdb';
15
+
16
+ export class MyResource extends Resource {
17
+ async post(target: RequestTargetOrId, record: any) {
18
+ if (record.data) {
19
+ // Convert base64-encoded string to a Buffer
20
+ record.data = Buffer.from(record.data, 'base64');
21
+ }
22
+ // Call the super method to perform the actual storage
23
+ return super.post(target, record);
24
+ }
25
+ }
26
+ ```
27
+
28
+ ## Responding with Binary Data
29
+
30
+ When you want to serve binary data (like an image or an MP3 file) back to the client, you can return a response object from your resource's `get` method. This object should include the appropriate `status`, `headers`, and the binary data itself in the `body`.
31
+
32
+ ### Example: Streaming an MP3 File
33
+
34
+ In this example, we retrieve a track from the database. If it contains binary data in the `data` field, we return it with the `audio/mpeg` content type.
35
+
36
+ ```typescript
37
+ import { RequestTarget, RequestTargetOrId, Resource } from 'harperdb';
38
+
39
+ export class TrackResource extends Resource {
40
+ async get(target: RequestTargetOrId) {
41
+ const id = (target as RequestTarget)?.id;
42
+ if (!id) {
43
+ return super.get(target);
44
+ }
45
+ const track = await super.get(target) as any;
46
+ if (track?.data) {
47
+ return {
48
+ status: 200,
49
+ headers: {
50
+ 'Content-Type': 'audio/mpeg',
51
+ 'Content-Disposition': `inline; filename="${track.name}.mp3"`,
52
+ },
53
+ body: track.data,
54
+ };
55
+ }
56
+ return track;
57
+ }
58
+ }
59
+ ```
60
+
61
+ ## Why Use Buffers?
62
+
63
+ - **Efficiency**: `Blob` fields are optimized for storing binary data. Buffers are the standard way to handle binary data in Node.js.
64
+ - **Compatibility**: Many HarperDB features and external libraries expect binary data to be in `Buffer` or `Uint8Array` format.
65
+ - **Storage**: Storing data as binary is more compact than storing it as a base64-encoded string.
@@ -0,0 +1,69 @@
1
+ # Querying through REST APIs in HarperDB
2
+
3
+ HarperDB's automatic REST APIs support powerful querying capabilities directly through URL query parameters. This allows you to filter, sort, paginate, and join data without writing complex queries.
4
+
5
+ ## Basic Filtering
6
+
7
+ The simplest way to filter is by using attribute names as query parameters:
8
+
9
+ `GET /ExamplePeople/?tag=friend`
10
+
11
+ This returns all records where `tag` equals `friend`.
12
+
13
+ ## Comparison Operators (FIQL-style)
14
+
15
+ You can use standard comparison operators by appending them to the attribute name with an `=` sign:
16
+
17
+ - `gt`: Greater than
18
+ - `ge`: Greater than or equal to
19
+ - `lt`: Less than
20
+ - `le`: Less than or equal to
21
+ - `ne`: Not equal
22
+
23
+ Example:
24
+ `GET /Products/?price=gt=100&price=lt=200`
25
+
26
+ ## Logic Operators
27
+
28
+ - **AND**: Use the `&` operator (default).
29
+ - **OR**: Use the `|` operator.
30
+
31
+ Example:
32
+ `GET /Products/?rating=5|featured=true`
33
+
34
+ ## Grouping
35
+
36
+ Use parentheses `()` to group conditions and indicate order of operations.
37
+
38
+ Example:
39
+ `GET /Products/?(rating=5|featured=true)&price=lt=50`
40
+
41
+ ## Selection
42
+
43
+ Use `select()` to limit the returned fields:
44
+
45
+ `GET /Products/?select(name,price)`
46
+
47
+ ## Pagination
48
+
49
+ Use `limit(start, end)` or `limit(end)`:
50
+
51
+ - `limit(10)`: Returns the first 10 records.
52
+ - `limit(20, 10)`: Skips the first 20 records and returns the next 10.
53
+
54
+ Example:
55
+ `GET /Products/?limit(0,20)`
56
+
57
+ ## Sorting
58
+
59
+ Use `sort()` with `+` (ascending) or `-` (descending) prefixes:
60
+
61
+ `GET /Products/?sort(+price,-rating)`
62
+
63
+ ## Joins and Chained Attributes
64
+
65
+ If you have defined relationships in your schema using the `@relationship` directive, you can use dot syntax to query across tables. For more on defining these, see the [Defining Relationships](defining-relationships.md) skill.
66
+
67
+ `GET /Book/?author.name=Harper`
68
+
69
+ This will perform an automatic join and filter books based on the related author's name.
@@ -0,0 +1,71 @@
1
+ # Real-time Applications in HarperDB
2
+
3
+ HarperDB provides built-in support for real-time data synchronization using WebSockets and a Pub/Sub mechanism. This allows clients to receive immediate updates when data changes in the database.
4
+
5
+ ## Implementing a WebSocket Resource
6
+
7
+ To handle WebSocket connections, implement the `connect` method in your custom resource class.
8
+
9
+ ### Example: `resources/exampleSocket.ts`
10
+
11
+ ```typescript
12
+ import {
13
+ type IterableEventQueue,
14
+ RequestTarget,
15
+ Resource,
16
+ tables,
17
+ } from 'harperdb';
18
+
19
+ export class ExampleSocket extends Resource {
20
+ async *connect(
21
+ target: RequestTarget,
22
+ incomingMessages: IterableEventQueue<any>,
23
+ ): AsyncIterable<any> {
24
+ // Subscribe to changes in a specific table
25
+ const subscription = await tables.ExamplePeople.subscribe(target);
26
+
27
+ if (!incomingMessages) {
28
+ // Server-Sent Events (SSE) mode: only outgoing messages
29
+ return subscription;
30
+ }
31
+
32
+ // Handle incoming messages from the client
33
+ for await (let message of incomingMessages) {
34
+ // Process message and optionally yield responses
35
+ yield { received: message };
36
+ }
37
+ }
38
+ }
39
+ ```
40
+
41
+ ## Pub/Sub with `tables.subscribe()`
42
+
43
+ You can subscribe to change events on any table using the `subscribe()` method. This is typically used within the `connect` method of a resource to stream updates to a connected client.
44
+
45
+ - `tables.TableName.subscribe(target)`: Subscribes to all changes in the specified table.
46
+ - The `target` parameter can include filters to only subscribe to a subset of changes.
47
+
48
+ ## Server-Sent Events (SSE)
49
+
50
+ If the client connects using a protocol that only supports one-way communication from the server (like standard SSE), the `incomingMessages` parameter will be null. Your `connect` method should handle this by only returning the subscription or yielding messages.
51
+
52
+ ## Using WebSockets from the Client
53
+
54
+ You can connect to your real-time resource using a standard WebSocket client.
55
+
56
+ ```javascript
57
+ const socket = new WebSocket('ws://your-harper-instance/ExampleSocket');
58
+
59
+ socket.onmessage = (event) => {
60
+ const data = JSON.parse(event.data);
61
+ console.log('Real-time update:', data);
62
+ };
63
+
64
+ socket.send(JSON.stringify({ type: 'ping' }));
65
+ ```
66
+
67
+ ## Key Real-time Features
68
+
69
+ - **Automatic Table Subscriptions**: Easily stream changes from any database table.
70
+ - **Bi-directional Communication**: Send and receive messages in real-time.
71
+ - **Scalable Pub/Sub**: HarperDB handles the efficient distribution of messages to subscribers.
@@ -0,0 +1,47 @@
1
+ # TypeScript Type Stripping
2
+
3
+ HarperDB supports using TypeScript directly without any additional build tools (like `tsc` or `esbuild`) by leveraging Node.js's native Type Stripping capability. This allows you to write `.ts` files for your Custom Resources and have them run directly in HarperDB.
4
+
5
+ ## Requirements
6
+
7
+ - **Node.js Version**: You must be running a version of Node.js that supports type stripping (Node.js v22.6.0 or higher).
8
+ - **No Experimental Flags**: When running on supported Node.js versions, HarperDB can automatically handle type stripping for your resource files.
9
+
10
+ ## Benefits
11
+
12
+ - **Faster Development**: No need to wait for a build step or manage complex build pipelines.
13
+ - **Simplified Tooling**: You don't need to install or configure `ts-node`, `tsx`, or other TypeScript execution engines for your HarperDB resources.
14
+ - **Native Performance**: Leverages Node.js's built-in support for stripping types, which is highly efficient.
15
+
16
+ ## Usage
17
+
18
+ Simply name your resource files with a `.ts` extension in your `resources/` directory.
19
+
20
+ ### Example: `resources/my-resource.ts`
21
+
22
+ ```typescript
23
+ import { Resource } from 'harperdb';
24
+
25
+ export class MyResource extends Resource {
26
+ async get() {
27
+ return { message: 'This is running directly from TypeScript!' };
28
+ }
29
+ }
30
+ ```
31
+
32
+ When cross-referencing between modules, ensure that the file path contains the appropriate extension.
33
+
34
+ ```typescript
35
+ import { MyResource } from './my-resource.ts';
36
+ ```
37
+
38
+ ## Configuration
39
+
40
+ In your `config.yaml`, ensure your `jsResource` points to your `.ts` files:
41
+
42
+ ```yaml
43
+ jsResource:
44
+ files: 'resources/*.ts'
45
+ ```
46
+
47
+ When HarperDB starts, it will detect the `.ts` files and, if running on a compatible Node.js version, will execute them using type stripping.