Browse Source

Add examples directory

Include examples for running the package.
master
TheoryOfNekomata 2 months ago
parent
commit
55053160ee
6 changed files with 103 additions and 102 deletions
  1. +1
    -1
      .gitignore
  2. +18
    -0
      examples/basic/data-source.ts
  3. +28
    -0
      examples/basic/serializers.ts
  4. +53
    -0
      examples/basic/server.ts
  5. +3
    -2
      src/data-sources/file-jsonl.ts
  6. +0
    -99
      src/server.ts

+ 1
- 1
.gitignore View File

@@ -105,5 +105,5 @@ dist
.tern-port

.npmrc
*.jsonl
examples/**/*.jsonl
.idea/

+ 18
- 0
examples/basic/data-source.ts View File

@@ -0,0 +1,18 @@
import {DataSource, dataSources, Resource} from '../../src';

export const autoIncrement = async (dataSource: DataSource) => {
const data = await dataSource.getMultiple() as Record<string, string>[];

const highestId = data.reduce<number>(
(highestId, d) => (Number(d.id) > highestId ? Number(d.id) : highestId),
-Infinity
);

if (Number.isFinite(highestId)) {
return (highestId + 1).toString();
}

return "1";
};

export const dataSource = (resource: Resource) => new dataSources.jsonlFile.DataSource(resource, 'examples/basic');

+ 28
- 0
examples/basic/serializers.ts View File

@@ -0,0 +1,28 @@
export const TEXT_SERIALIZER_PAIR = {
serialize(obj: unknown, level = 0): string {
if (Array.isArray(obj)) {
return obj.map((o) => this.serialize(o)).join('\n\n');
}

if (typeof obj === 'object') {
if (obj !== null) {
return Object.entries(obj)
.map(([key, value]) => `${Array(level * 2).fill(' ').join('')}${key}: ${this.serialize(value, level + 1)}`)
.join('\n');
}

return '';
}

if (typeof obj === 'number' && Number.isFinite(obj)) {
return obj.toString();
}

if (typeof obj === 'string') {
return obj;
}

return '';
},
deserialize: <T>(str: string) => str as T
};

+ 53
- 0
examples/basic/server.ts View File

@@ -0,0 +1,53 @@
import {
application,
resource,
valibot as v,
serializers
} from '../../src';
import {TEXT_SERIALIZER_PAIR} from './serializers';
import {autoIncrement, dataSource} from './data-source';

const Piano = resource(v.object(
{
brand: v.string()
},
v.never()
))
.name('Piano')
.id('id', {
generationStrategy: autoIncrement,
});

// TODO implement authentication and RBAC on each resource

const User = resource(v.object(
{
firstName: v.string(),
middleName: v.string(),
lastName: v.string(),
bio: v.string(),
birthday: v.datelike()
},
v.never()
))
.name('User')
.fullText('bio')
.id('id', {
generationStrategy: autoIncrement,
});

const app = application({
name: 'piano-service',
dataSource,
})
.contentType('application/json', serializers.applicationJson)
.contentType('text/json', serializers.textJson)
.contentType('text/plain', TEXT_SERIALIZER_PAIR)
.resource(Piano)
.resource(User);

const server = app.createServer({
baseUrl: '/api'
});

server.listen(3000);

+ 3
- 2
src/data-sources/file-jsonl.ts View File

@@ -1,4 +1,5 @@
import {readFile, writeFile} from 'fs/promises';
import {join} from 'path';
import {DataSource as DataSourceInterface, Resource} from '../core';

export class DataSource<T extends Record<string, string>> implements DataSourceInterface<T> {
@@ -6,8 +7,8 @@ export class DataSource<T extends Record<string, string>> implements DataSourceI

data: T[] = [];

constructor(private readonly resource: Resource) {
this.path = `${this.resource.collectionName}.jsonl`;
constructor(private readonly resource: Resource, private readonly baseDir = '') {
this.path = join(baseDir, `${this.resource.collectionName}.jsonl`);
}

async initialize() {


+ 0
- 99
src/server.ts View File

@@ -1,99 +0,0 @@
import {
application,
DataSource,
resource,
valibot as v,
dataSources,
serializers
} from '.';

const autoIncrement = async (dataSource: DataSource) => {
const data = await dataSource.getMultiple() as Record<string, string>[];

const highestId = data.reduce<number>(
(highestId, d) => (Number(d.id) > highestId ? Number(d.id) : highestId),
-Infinity
);

if (Number.isFinite(highestId)) {
return (highestId + 1).toString();
}

return "1";
};


const TEXT_SERIALIZER_PAIR = {
serialize(obj: unknown, level = 0): string {
if (Array.isArray(obj)) {
return obj.map((o) => this.serialize(o)).join('\n\n');
}

if (typeof obj === 'object') {
if (obj !== null) {
return Object.entries(obj)
.map(([key, value]) => `${Array(level * 2).fill(' ').join('')}${key}: ${this.serialize(value, level + 1)}`)
.join('\n');
}

return '';
}

if (typeof obj === 'number' && Number.isFinite(obj)) {
return obj.toString();
}

if (typeof obj === 'string') {
return obj;
}

return '';
},
deserialize: <T>(str: string) => str as T
};

const Piano = resource(v.object(
{
brand: v.string()
},
v.never()
))
.name('Piano')
.id('id', {
generationStrategy: autoIncrement,
});

// TODO implement authentication and RBAC on each resource

const User = resource(v.object(
{
firstName: v.string(),
middleName: v.string(),
lastName: v.string(),
bio: v.string(),
birthday: v.datelike()
},
v.never()
))
.name('User')
.fullText('bio')
.id('id', {
generationStrategy: autoIncrement,
});

const app = application({
name: 'piano-service',
dataSource: (resource) => new dataSources.jsonlFile.DataSource(resource),
})
.contentType('application/json', serializers.applicationJson)
.contentType('text/json', serializers.textJson)
.contentType('text/plain', TEXT_SERIALIZER_PAIR)
.resource(Piano)
.resource(User);

const server = app.createServer({
baseUrl: '/api'
});

server.listen(3000);


Loading…
Cancel
Save