@alstar/studio 0.0.0-beta.1

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.
@@ -0,0 +1,44 @@
1
+ type Block = {
2
+ id: number
3
+ name: string
4
+ label: string
5
+ type: string
6
+ sort_order: number
7
+ value: string | null
8
+ options: any // JSON-parsed if necessary
9
+ parent_block_id: number | null
10
+ depth: number
11
+ // ... you can add other fields if needed
12
+ }
13
+
14
+ type BlockWithChildren = Block & { fields: BlockWithChildren[] }
15
+
16
+ export function buildBlockTree(blocks: Block[]): BlockWithChildren {
17
+ const blockMap = new Map<number, BlockWithChildren>()
18
+
19
+ // Initialize map with all blocks and empty `fields` array
20
+ for (const block of blocks) {
21
+ blockMap.set(block.id, { ...block, fields: [] })
22
+ }
23
+
24
+ const tree: BlockWithChildren[] = []
25
+
26
+ for (const block of blocks) {
27
+ const current = blockMap.get(block.id)!
28
+
29
+ if (block.parent_block_id != null) {
30
+ const parent = blockMap.get(block.parent_block_id)
31
+ if (parent) {
32
+ parent.fields.push(current)
33
+ } else {
34
+ console.warn(
35
+ `Parent with id ${block.parent_block_id} not found for block ${block.id}`,
36
+ )
37
+ }
38
+ } else {
39
+ tree.push(current) // top-level (root) blocks
40
+ }
41
+ }
42
+
43
+ return tree[0]
44
+ }
@@ -0,0 +1,8 @@
1
+ import { db } from '@alstar/db'
2
+ import * as schemas from '../schemas.ts'
3
+
4
+ export function createStudioTables() {
5
+ Object.values(schemas).forEach((schema) => {
6
+ db.createTableRaw(schema.tableName, schema.columns)
7
+ })
8
+ }
@@ -0,0 +1,58 @@
1
+ import fs from 'node:fs/promises'
2
+ import path from 'node:path'
3
+ import { Hono } from 'hono'
4
+ import { type HtmlEscapedString } from 'hono/utils/html'
5
+
6
+ type Page<C> = (c?: C) => HtmlEscapedString | Promise<HtmlEscapedString>
7
+
8
+ export const fileBasedRouter = async (rootdir: string) => {
9
+ const router = new Hono()
10
+
11
+ const root = path.resolve(rootdir)
12
+ const dirs = await fs.readdir(root, { recursive: true })
13
+ const files = dirs.filter((dir) => path.extname(dir))
14
+
15
+ await Promise.all(
16
+ files.map(async (file) => {
17
+ const pagePath = path.join(root, file)
18
+ const page = Object.values(await import(pagePath)).at(-1)
19
+
20
+ const relativePageFilePath = pagePath
21
+ .split(rootdir.replace('.', ''))
22
+ .at(-1)
23
+
24
+ if (!relativePageFilePath) return
25
+
26
+ const pageFilePathWithoutExt = relativePageFilePath.replace(
27
+ path.extname(relativePageFilePath),
28
+ '',
29
+ )
30
+
31
+ if (pageFilePathWithoutExt === '/index') {
32
+ if (typeof page !== 'function') {
33
+ router.get('/', (c) => c.notFound())
34
+ return
35
+ }
36
+
37
+ router.get('/', (c) => c.html((page as Page<typeof c>)(c)))
38
+ return
39
+ }
40
+
41
+ const routePath = pageFilePathWithoutExt.replaceAll('/index', '')
42
+
43
+ const route = routePath.replace(
44
+ /\[([^\]]+)\]/g, // [foo] and [bar]
45
+ (_match, content) => `:${content}`, // :foo and :bar
46
+ )
47
+
48
+ if (typeof page !== 'function') {
49
+ router.get(route, (c) => c.notFound())
50
+ return
51
+ }
52
+
53
+ router.get(route, (c) => c.html((page as Page<typeof c>)(c)))
54
+ }),
55
+ )
56
+
57
+ return router
58
+ }
@@ -0,0 +1,26 @@
1
+ import fs from 'node:fs/promises'
2
+ import path from 'node:path'
3
+
4
+ const CONFIG_FILE_NAME = 'alstar.config.ts'
5
+
6
+ async function fileExists(filepath: string) {
7
+ // does the file exist?
8
+ try {
9
+ await fs.stat(filepath)
10
+ } catch (error) {
11
+ return {}
12
+ }
13
+ }
14
+
15
+ export const getConfig = async <P>(): Promise<P> => {
16
+ const root = path.resolve('./')
17
+
18
+ if (!(await fileExists(path.join(root, CONFIG_FILE_NAME)))) {
19
+ return {} as P
20
+ }
21
+
22
+ const module = await import(path.join(root, CONFIG_FILE_NAME))
23
+ const config = Object.values(module)[0]
24
+
25
+ return config as P
26
+ }
@@ -0,0 +1,10 @@
1
+ export function slugify(str: string) {
2
+ return String(str)
3
+ .normalize('NFKD') // split accented characters into their base characters and diacritical marks
4
+ .replace(/[\u0300-\u036f]/g, '') // remove all the accents, which happen to be all in the \u03xx UNICODE block.
5
+ .trim() // trim leading or trailing whitespace
6
+ .toLowerCase() // convert to lowercase
7
+ .replace(/[^a-z0-9 -]/g, '') // remove non-alphanumeric characters
8
+ .replace(/\s+/g, '-') // replace spaces with hyphens
9
+ .replace(/-+/g, '-') // remove consecutive hyphens
10
+ }
package/utils/sql.ts ADDED
@@ -0,0 +1 @@
1
+ export const sql = String.raw
@@ -0,0 +1,5 @@
1
+ import { type HtmlEscapedString } from 'hono/utils/html'
2
+
3
+ export const stripNewlines = (
4
+ str: string | HtmlEscapedString | Promise<HtmlEscapedString>
5
+ ) => str.toString().replaceAll('\n', '')