@alstar/studio 0.0.0-beta.1 → 0.0.0-beta.11

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.
Files changed (69) hide show
  1. package/api/api-key.ts +69 -0
  2. package/api/auth.ts +66 -0
  3. package/api/backup.ts +40 -0
  4. package/api/block.ts +131 -66
  5. package/api/index.ts +19 -1
  6. package/api/mcp.ts +50 -0
  7. package/components/AdminPanel.ts +87 -0
  8. package/components/Backup.ts +13 -0
  9. package/components/BlockFieldRenderer.ts +125 -0
  10. package/components/BlockRenderer.ts +22 -0
  11. package/components/Entries.ts +20 -12
  12. package/components/Entry.ts +13 -21
  13. package/components/FieldRenderer.ts +35 -0
  14. package/components/Render.ts +46 -0
  15. package/components/Settings.ts +104 -0
  16. package/components/SiteLayout.ts +61 -0
  17. package/components/Users.ts +46 -0
  18. package/components/fields/Markdown.ts +44 -0
  19. package/components/fields/Slug.ts +113 -0
  20. package/components/fields/Text.ts +42 -0
  21. package/components/fields/index.ts +7 -0
  22. package/components/icons.ts +136 -7
  23. package/index.ts +94 -34
  24. package/package.json +10 -7
  25. package/pages/entry/[id].ts +15 -0
  26. package/pages/error.ts +14 -0
  27. package/{components → pages}/index.ts +7 -4
  28. package/pages/login.ts +21 -0
  29. package/pages/register.ts +33 -0
  30. package/pages/settings.ts +8 -0
  31. package/public/studio/css/admin-panel.css +103 -0
  32. package/public/studio/css/blocks-field.css +53 -0
  33. package/public/studio/css/settings.css +28 -0
  34. package/public/studio/js/markdown-editor.js +34 -0
  35. package/public/studio/js/sortable-list.js +50 -0
  36. package/public/studio/main.css +166 -0
  37. package/public/studio/main.js +21 -0
  38. package/queries/block-2.ts +339 -0
  39. package/queries/block-with-children.ts +74 -0
  40. package/queries/block.ts +289 -0
  41. package/queries/db-types.ts +15 -0
  42. package/queries/getBlockTrees-2.ts +71 -0
  43. package/queries/getBlockTrees.ts +316 -0
  44. package/queries/getBlocks.ts +214 -0
  45. package/queries/index.ts +2 -98
  46. package/queries/structure-types.ts +97 -0
  47. package/readme.md +205 -0
  48. package/schema.sql +18 -0
  49. package/schemas.ts +23 -52
  50. package/types.ts +144 -5
  51. package/utils/auth.ts +54 -0
  52. package/utils/buildBlocksTree.ts +4 -4
  53. package/utils/create-hash.ts +9 -0
  54. package/utils/define.ts +39 -0
  55. package/utils/file-based-router.ts +11 -2
  56. package/utils/get-config.ts +8 -9
  57. package/utils/get-or-create-row.ts +41 -0
  58. package/utils/html.ts +247 -0
  59. package/utils/startup-log.ts +19 -0
  60. package/components/AdminPanel/AdminPanel.css +0 -59
  61. package/components/AdminPanel/AdminPanel.ts +0 -57
  62. package/components/Block.ts +0 -116
  63. package/components/Entry.css +0 -7
  64. package/components/Field.ts +0 -164
  65. package/components/Fields.ts +0 -43
  66. package/components/layout.ts +0 -53
  67. package/public/main.css +0 -92
  68. package/public/main.js +0 -43
  69. /package/public/{favicon.svg → studio/favicon.svg} +0 -0
@@ -1,164 +0,0 @@
1
- import { html } from 'hono/html'
2
- import { type Block } from '../types.ts'
3
- import { type HtmlEscapedString } from 'hono/utils/html'
4
- import { query } from '../queries/index.ts'
5
- import { db } from '@alstar/db'
6
- import BlockComponent from './Block.ts'
7
- import {
8
- buildStructurePath,
9
- type StructurePath,
10
- } from '../utils/build-structure-path.ts'
11
-
12
- function getData(parentId: string | number, field: Block, sortOrder: number) {
13
- const data = query.block({
14
- parent: parentId?.toString() || null,
15
- name: field.name,
16
- sort_order: sortOrder.toString(),
17
- })
18
-
19
- if (!data) {
20
- const change = db.insertInto('blocks', {
21
- name: field.name?.toString(),
22
- label: field.label?.toString(),
23
- type: field.type?.toString(),
24
- sort_order: sortOrder,
25
- parent_block_id: parentId,
26
- })
27
-
28
- return query.block({ id: change.lastInsertRowid.toString() })
29
- }
30
-
31
- return data
32
- }
33
-
34
- const Field = (props: {
35
- entryId: string | number
36
- parentId: string | number
37
- blockStructure: Block
38
- sortOrder?: number
39
- structurePath: StructurePath
40
- }): HtmlEscapedString | Promise<HtmlEscapedString> => {
41
- const {
42
- entryId,
43
- parentId,
44
- blockStructure,
45
- sortOrder = 0,
46
- structurePath,
47
- } = props
48
-
49
- const data = getData(parentId, blockStructure, sortOrder)
50
-
51
- if (!data) return html`<p>No block</p>`
52
-
53
- const fieldStructurePath = buildStructurePath(blockStructure, structurePath)
54
-
55
- return html`
56
- ${blockStructure.type === 'slug' &&
57
- html`
58
- <form
59
- data-on-input="@patch('/admin/api/block', { contentType: 'form' })"
60
- >
61
- <label for="block-${data.id}">${blockStructure.label}</label>
62
- <input
63
- id="block-${data.id}"
64
- name="value"
65
- type="text"
66
- value="${data.value}"
67
- />
68
-
69
- <input type="hidden" name="type" value="${blockStructure.type}" />
70
- <input type="hidden" name="id" value="${data.id}" />
71
- <input type="hidden" name="entryId" value="${entryId}" />
72
- <input type="hidden" name="parentId" value="${parentId}" />
73
- <input type="hidden" name="sort_order" value="${sortOrder}" />
74
- <input
75
- type="hidden"
76
- name="path"
77
- value="${fieldStructurePath.join('.')}"
78
- />
79
- </form>
80
- `}
81
- ${blockStructure.type === 'text' &&
82
- html`
83
- <form
84
- data-on-input="@patch('/admin/api/block', { contentType: 'form' })"
85
- >
86
- <label for="block-${data.id}">${blockStructure.label}</label>
87
- <input
88
- id="block-${data.id}"
89
- name="value"
90
- type="text"
91
- value="${data.value}"
92
- />
93
-
94
- <input type="hidden" name="type" value="${blockStructure.type}" />
95
- <input type="hidden" name="id" value="${data.id}" />
96
- <input type="hidden" name="entryId" value="${entryId}" />
97
- <input type="hidden" name="parentId" value="${parentId}" />
98
- <input type="hidden" name="sort_order" value="${sortOrder}" />
99
- <input
100
- type="hidden"
101
- name="path"
102
- value="${fieldStructurePath.join('.')}"
103
- />
104
- </form>
105
- `}
106
- ${blockStructure.type === 'image' &&
107
- html`
108
- <form
109
- data-on-input="@patch('/admin/api/block', { contentType: 'form' })"
110
- >
111
- <label for="block-${data.id}">${blockStructure.label}</label>
112
- <input
113
- id="block-${data.id}"
114
- name="value"
115
- type="text"
116
- value="${data.value}"
117
- />
118
-
119
- <input type="hidden" name="type" value="${blockStructure.type}" />
120
- <input type="hidden" name="id" value="${data.id}" />
121
- <input type="hidden" name="entryId" value="${entryId}" />
122
- <input type="hidden" name="parentId" value="${parentId}" />
123
- <input type="hidden" name="sort_order" value="${sortOrder}" />
124
- <input
125
- type="hidden"
126
- name="path"
127
- value="${fieldStructurePath.join('.')}"
128
- />
129
- </form>
130
- `}
131
- ${blockStructure.type === 'markdown' &&
132
- html`
133
- <form
134
- data-on-input="@patch('/admin/api/block', { contentType: 'form' })"
135
- >
136
- <label for="block-${data.id}">${blockStructure.label}</label>
137
-
138
- <textarea></textarea>
139
-
140
- <!-- <input
141
- id="block-${data.id}"
142
- name="value"
143
- type="text"
144
- value="${data.value}"
145
- /> -->
146
-
147
- <input type="hidden" name="type" value="${blockStructure.type}" />
148
- <input type="hidden" name="id" value="${data.id}" />
149
- <input type="hidden" name="entryId" value="${entryId}" />
150
- <input type="hidden" name="parentId" value="${parentId}" />
151
- <input type="hidden" name="sort_order" value="${sortOrder}" />
152
- <input
153
- type="hidden"
154
- name="path"
155
- value="${fieldStructurePath.join('.')}"
156
- />
157
- </form>
158
- `}
159
- ${blockStructure.type === 'blocks' &&
160
- BlockComponent(entryId, data.id, blockStructure, fieldStructurePath)}
161
- `
162
- }
163
-
164
- export default Field
@@ -1,43 +0,0 @@
1
- import { html } from 'hono/html'
2
- import { type Block } from '../types.ts'
3
- import { type HtmlEscapedString } from 'hono/utils/html'
4
- import Field from './Field.ts'
5
- import {
6
- buildStructurePath,
7
- type StructurePath,
8
- } from '../utils/build-structure-path.ts'
9
-
10
- const Fields = (props: {
11
- entryId: string | number
12
- parentId: string | number
13
- blockStructure: Block
14
- structurePath: StructurePath
15
- }): HtmlEscapedString | Promise<HtmlEscapedString> => {
16
- const updatedPath = buildStructurePath(
17
- props.blockStructure,
18
- props.structurePath,
19
- )
20
-
21
- return html`
22
- <div class="fields">
23
- ${props.blockStructure.fields
24
- ? props.blockStructure.fields?.map((field, idx) => {
25
- return Field({
26
- entryId: props.entryId,
27
- parentId: props.parentId,
28
- blockStructure: field,
29
- sortOrder: idx,
30
- structurePath: [...updatedPath, 'fields'],
31
- })
32
- })
33
- : Field({
34
- entryId: props.entryId,
35
- parentId: props.parentId,
36
- blockStructure: props.blockStructure,
37
- structurePath: updatedPath,
38
- })}
39
- </div>
40
- `
41
- }
42
-
43
- export default Fields
@@ -1,53 +0,0 @@
1
- import adminPanel from './AdminPanel/AdminPanel.ts'
2
- import { html } from 'hono/html'
3
- import { type HtmlEscapedString } from 'hono/utils/html'
4
- import { rootdir } from '../index.ts'
5
- import { type Structure } from '../types.ts'
6
-
7
- export default (props: {
8
- content:
9
- | string
10
- | Promise<string>
11
- | HtmlEscapedString
12
- | Promise<HtmlEscapedString>
13
- structure: Structure
14
- }) => {
15
- return html`
16
- <!DOCTYPE html>
17
- <html lang="en">
18
- <head>
19
- <meta charset="UTF-8" />
20
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
21
- <title>Alster CMS</title>
22
-
23
- <link
24
- rel="icon"
25
- type="image/svg"
26
- href="${rootdir}/public/favicon.svg"
27
- />
28
-
29
- <meta name="color-scheme" content="light dark" />
30
-
31
- <link rel="stylesheet" href="${rootdir}/public/main.css" />
32
-
33
- <script
34
- type="module"
35
- src="https://cdn.jsdelivr.net/gh/starfederation/datastar@main/bundles/datastar.js"
36
- ></script>
37
- <script src="https://unpkg.com/@barba/core@2.10.3/dist/barba.umd.js"></script>
38
- </head>
39
-
40
- <body data-barba="wrapper">
41
- <section>${adminPanel(props.structure)}</section>
42
-
43
- <main style="height: 100vh; overflow: auto">
44
- <section data-barba="container" data-barba-namespace="default">
45
- ${props.content}
46
- </section>
47
- </main>
48
-
49
- <script src="${rootdir}/public/main.js" type="module"></script>
50
- </body>
51
- </html>
52
- `
53
- }
package/public/main.css DELETED
@@ -1,92 +0,0 @@
1
- @import './../node_modules/@alstar/ui/red.css';
2
-
3
- body {
4
- min-height: 100vh;
5
- }
6
-
7
- body {
8
- padding: 0;
9
- min-height: inherit;
10
-
11
- display: grid;
12
- grid-template-columns: auto 1fr;
13
- align-content: baseline;
14
-
15
- > main {
16
- padding: 40px;
17
-
18
- section {
19
- max-width: 900px;
20
- margin: 0 auto;
21
- }
22
- }
23
- }
24
-
25
- .entry > .fields > .block {
26
- padding-block: var(--pico-spacing);
27
-
28
- > header {
29
- margin-block: var(--pico-block-spacing-vertical);
30
- }
31
- }
32
-
33
- .block {
34
- > header {
35
- margin-bottom: var(--pico-spacing);
36
- }
37
-
38
- header {
39
- display: flex;
40
- justify-content: space-between;
41
- align-items: center;
42
-
43
- background-color: inherit;
44
-
45
- h6,
46
- h5,
47
- fieldset {
48
- margin-bottom: 0;
49
- }
50
-
51
- button {
52
- padding: 0;
53
- background-color: white;
54
-
55
- svg {
56
- padding: 8px;
57
- }
58
- }
59
- }
60
- }
61
-
62
- [data-sortable] {
63
- > article {
64
- transition: opacity 200ms;
65
- }
66
-
67
- .sortable-ghost {
68
- opacity: 0.3;
69
- }
70
-
71
- /* .sortable-chosen {
72
- filter: brightness(0.9)
73
- } */
74
- }
75
-
76
- div.ink-mde {
77
- border: var(--pico-border-width) solid #2a3140;
78
- border-radius: var(--pico-border-radius);
79
- outline: 0;
80
- background-color: var(--pico-background-color);
81
- box-shadow: var(--pico-box-shadow);
82
- color: var(--pico-color);
83
- }
84
-
85
- .ink-mde-textarea {
86
- width: 100%;
87
- }
88
-
89
- .disclamer {
90
- display: flex;
91
- justify-content: center;
92
- }
package/public/main.js DELETED
@@ -1,43 +0,0 @@
1
- import Sortable from '../node_modules/sortablejs/modular/sortable.core.esm.js'
2
- import { ink, wrap } from 'https://esm.sh/ink-mde@0.34.0'
3
-
4
- barba.init({
5
- views: [
6
- {
7
- namespace: 'default',
8
- afterEnter() {
9
- init()
10
- },
11
- },
12
- ],
13
- })
14
-
15
- function init() {
16
- // sortable
17
- {
18
- const els = document.querySelectorAll('[data-sortable]')
19
-
20
- els.forEach((el) => {
21
- var sortable = Sortable.create(el, {
22
- delay: 0,
23
- animation: 250,
24
- dragClass: 'sortable-drag',
25
- easing: 'ease-in-out',
26
- })
27
- })
28
- }
29
-
30
- // ink-mde
31
- {
32
- const el = document.querySelector('textarea')
33
-
34
- if (el) {
35
- wrap(el, {
36
- interface: {
37
- // appearance: InkValues.Appearance.Auto,
38
- attribution: false,
39
- },
40
- })
41
- }
42
- }
43
- }
File without changes