chadstart 1.0.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.
Files changed (115) hide show
  1. package/.dockerignore +10 -0
  2. package/.env.example +46 -0
  3. package/.github/workflows/browser-test.yml +34 -0
  4. package/.github/workflows/docker-publish.yml +54 -0
  5. package/.github/workflows/docs.yml +31 -0
  6. package/.github/workflows/npm-chadstart.yml +27 -0
  7. package/.github/workflows/npm-sdk.yml +38 -0
  8. package/.github/workflows/test.yml +85 -0
  9. package/.weblate +9 -0
  10. package/Dockerfile +23 -0
  11. package/README.md +348 -0
  12. package/admin/index.html +2802 -0
  13. package/admin/login.html +207 -0
  14. package/chadstart.example.yml +416 -0
  15. package/chadstart.schema.json +367 -0
  16. package/chadstart.yaml +53 -0
  17. package/cli/cli.js +295 -0
  18. package/core/api-generator.js +606 -0
  19. package/core/auth.js +298 -0
  20. package/core/db.js +384 -0
  21. package/core/entity-engine.js +166 -0
  22. package/core/error-reporter.js +132 -0
  23. package/core/file-storage.js +97 -0
  24. package/core/functions-engine.js +353 -0
  25. package/core/openapi.js +171 -0
  26. package/core/plugin-loader.js +92 -0
  27. package/core/realtime.js +93 -0
  28. package/core/schema-validator.js +50 -0
  29. package/core/seeder.js +231 -0
  30. package/core/telemetry.js +119 -0
  31. package/core/upload.js +372 -0
  32. package/core/workers/php_worker.php +19 -0
  33. package/core/workers/python_worker.py +33 -0
  34. package/core/workers/ruby_worker.rb +21 -0
  35. package/core/yaml-loader.js +64 -0
  36. package/demo/chadstart.yaml +178 -0
  37. package/demo/docker-compose.yml +31 -0
  38. package/demo/functions/greet.go +39 -0
  39. package/demo/functions/hello.cpp +18 -0
  40. package/demo/functions/hello.py +13 -0
  41. package/demo/functions/hello.rb +10 -0
  42. package/demo/functions/onTodoCreated.js +13 -0
  43. package/demo/functions/ping.sh +13 -0
  44. package/demo/functions/stats.js +22 -0
  45. package/demo/public/index.html +522 -0
  46. package/docker-compose.yml +17 -0
  47. package/docs/access-policies.md +155 -0
  48. package/docs/admin-ui.md +29 -0
  49. package/docs/angular.md +69 -0
  50. package/docs/astro.md +71 -0
  51. package/docs/auth.md +160 -0
  52. package/docs/cli.md +56 -0
  53. package/docs/config.md +127 -0
  54. package/docs/crud.md +627 -0
  55. package/docs/deploy.md +113 -0
  56. package/docs/docker.md +59 -0
  57. package/docs/entities.md +385 -0
  58. package/docs/functions.md +196 -0
  59. package/docs/getting-started.md +79 -0
  60. package/docs/groups.md +85 -0
  61. package/docs/index.md +5 -0
  62. package/docs/llm-rules.md +81 -0
  63. package/docs/middlewares.md +78 -0
  64. package/docs/overrides/home.html +350 -0
  65. package/docs/plugins.md +59 -0
  66. package/docs/react.md +75 -0
  67. package/docs/realtime.md +43 -0
  68. package/docs/s3-storage.md +40 -0
  69. package/docs/security.md +23 -0
  70. package/docs/stylesheets/extra.css +375 -0
  71. package/docs/svelte.md +71 -0
  72. package/docs/telemetry.md +97 -0
  73. package/docs/upload.md +168 -0
  74. package/docs/validation.md +115 -0
  75. package/docs/vue.md +86 -0
  76. package/docs/webhooks.md +87 -0
  77. package/index.js +11 -0
  78. package/locales/en/admin.json +169 -0
  79. package/mkdocs.yml +82 -0
  80. package/package.json +65 -0
  81. package/playwright.config.js +24 -0
  82. package/public/.gitkeep +0 -0
  83. package/sdk/README.md +284 -0
  84. package/sdk/package.json +39 -0
  85. package/sdk/scripts/build.js +58 -0
  86. package/sdk/src/index.js +368 -0
  87. package/sdk/test/sdk.test.cjs +340 -0
  88. package/sdk/types/index.d.ts +217 -0
  89. package/server/express-server.js +734 -0
  90. package/test/access-policies.test.js +96 -0
  91. package/test/ai.test.js +81 -0
  92. package/test/api-keys.test.js +361 -0
  93. package/test/auth.test.js +122 -0
  94. package/test/browser/admin-ui.spec.js +127 -0
  95. package/test/browser/global-setup.js +71 -0
  96. package/test/browser/global-teardown.js +11 -0
  97. package/test/db.test.js +227 -0
  98. package/test/entity-engine.test.js +193 -0
  99. package/test/error-reporter.test.js +140 -0
  100. package/test/functions-engine.test.js +240 -0
  101. package/test/groups.test.js +212 -0
  102. package/test/hot-reload.test.js +153 -0
  103. package/test/i18n.test.js +173 -0
  104. package/test/middleware.test.js +76 -0
  105. package/test/openapi.test.js +67 -0
  106. package/test/schema-validator.test.js +83 -0
  107. package/test/sdk.test.js +90 -0
  108. package/test/seeder.test.js +279 -0
  109. package/test/settings.test.js +109 -0
  110. package/test/telemetry.test.js +254 -0
  111. package/test/test.js +17 -0
  112. package/test/upload.test.js +265 -0
  113. package/test/validation.test.js +96 -0
  114. package/test/yaml-loader.test.js +93 -0
  115. package/utils/logger.js +24 -0
@@ -0,0 +1,367 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://chadstart.com/chadstart.schema.json",
4
+ "title": "ChadStart Configuration",
5
+ "description": "Schema for chadstart.yaml — define your entire backend in one YAML file.",
6
+ "type": "object",
7
+ "required": ["name"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "name": {
11
+ "type": "string",
12
+ "description": "The name of your application."
13
+ },
14
+ "port": {
15
+ "type": "integer",
16
+ "default": 3000,
17
+ "description": "The port your server listens on."
18
+ },
19
+ "database": {
20
+ "type": "string",
21
+ "description": "Path to the SQLite database file, relative to this config file (default: data/chadstart.db in the working directory, overridden by DB_PATH env var)."
22
+ },
23
+ "entities": {
24
+ "type": "object",
25
+ "description": "Map of entity names to their definitions.",
26
+ "additionalProperties": { "$ref": "#/$defs/entity" }
27
+ },
28
+ "functions": {
29
+ "type": "object",
30
+ "description": "Map of custom function-based endpoint names to their definitions.",
31
+ "additionalProperties": { "$ref": "#/$defs/endpoint" }
32
+ },
33
+ "groups": {
34
+ "type": "object",
35
+ "description": "Reusable property groups that can be embedded in entities.",
36
+ "additionalProperties": { "$ref": "#/$defs/group" }
37
+ },
38
+ "files": {
39
+ "type": "object",
40
+ "description": "Map of file bucket names to their definitions.",
41
+ "additionalProperties": { "$ref": "#/$defs/fileBucket" }
42
+ },
43
+ "public": {
44
+ "type": "object",
45
+ "required": ["folder"],
46
+ "additionalProperties": false,
47
+ "properties": {
48
+ "folder": {
49
+ "type": "string",
50
+ "description": "Path to the public static files directory."
51
+ }
52
+ }
53
+ },
54
+ "plugins": {
55
+ "type": "array",
56
+ "items": { "$ref": "#/$defs/plugin" }
57
+ },
58
+ "admin": {
59
+ "type": "object",
60
+ "description": "Admin UI and Admin entity configuration.",
61
+ "additionalProperties": false,
62
+ "properties": {
63
+ "enable_app": {
64
+ "type": "boolean",
65
+ "default": true,
66
+ "description": "Enable the Admin UI at /admin. Default: true."
67
+ },
68
+ "enable_entity": {
69
+ "type": "boolean",
70
+ "default": true,
71
+ "description": "Enable the built-in Admin entity (email + password authenticable entity). Default: true."
72
+ },
73
+ "policies": {
74
+ "type": "array",
75
+ "items": { "$ref": "#/$defs/policy" },
76
+ "description": "Access policies for the /admin route. Default: [{ access: admin }]."
77
+ }
78
+ }
79
+ },
80
+ "rateLimits": {
81
+ "type": "array",
82
+ "description": "Rate limit definitions applied to API routes.",
83
+ "items": { "$ref": "#/$defs/rateLimit" }
84
+ },
85
+ "telemetry": {
86
+ "type": "object",
87
+ "description": "OpenTelemetry tracing configuration. Secret values (auth headers / API keys) must be supplied via environment variables only — never put secrets in this file.",
88
+ "additionalProperties": false,
89
+ "properties": {
90
+ "enabled": {
91
+ "type": "boolean",
92
+ "default": false,
93
+ "description": "Enable OpenTelemetry tracing. Also configurable via OTEL_ENABLED=true env var."
94
+ },
95
+ "serviceName": {
96
+ "type": "string",
97
+ "description": "Service name reported to the OTLP collector. Overridable via OTEL_SERVICE_NAME env var."
98
+ },
99
+ "endpoint": {
100
+ "type": "string",
101
+ "description": "OTLP collector base URL (e.g. http://localhost:4318). Overridable via OTEL_EXPORTER_OTLP_ENDPOINT env var."
102
+ }
103
+ }
104
+ },
105
+ "sentry": {
106
+ "type": "object",
107
+ "description": "Sentry (or Bugsink) error-reporting configuration. The DSN is a secret and must be provided via the SENTRY_DSN environment variable — do NOT put it here.",
108
+ "additionalProperties": false,
109
+ "properties": {
110
+ "environment": {
111
+ "type": "string",
112
+ "description": "The environment label sent to Sentry (e.g. production, staging). Defaults to NODE_ENV."
113
+ },
114
+ "tracesSampleRate": {
115
+ "type": "number",
116
+ "minimum": 0,
117
+ "maximum": 1,
118
+ "default": 1.0,
119
+ "description": "Fraction of transactions to sample for performance monitoring (0.0–1.0)."
120
+ },
121
+ "debug": {
122
+ "type": "boolean",
123
+ "default": false,
124
+ "description": "Enable Sentry SDK debug logging."
125
+ }
126
+ }
127
+ }
128
+ },
129
+ "$defs": {
130
+ "property": {
131
+ "oneOf": [
132
+ { "type": "string", "description": "Short syntax: property name (type defaults to string)." },
133
+ {
134
+ "type": "object",
135
+ "required": ["name"],
136
+ "properties": {
137
+ "name": { "type": "string" },
138
+ "type": {
139
+ "type": "string",
140
+ "enum": [
141
+ "string", "text", "richText", "number", "link", "money",
142
+ "date", "timestamp", "email", "boolean", "file", "image",
143
+ "password", "choice", "location", "group", "json",
144
+ "integer", "float", "real"
145
+ ],
146
+ "default": "string"
147
+ },
148
+ "hidden": { "type": "boolean", "default": false },
149
+ "options": { "type": "object" },
150
+ "validation": { "$ref": "#/$defs/validationRules" },
151
+ "helpText": { "type": "string" },
152
+ "default": {}
153
+ },
154
+ "additionalProperties": false
155
+ }
156
+ ]
157
+ },
158
+ "relationItem": {
159
+ "oneOf": [
160
+ { "type": "string", "description": "Short syntax: entity name." },
161
+ {
162
+ "type": "object",
163
+ "required": ["name", "entity"],
164
+ "properties": {
165
+ "name": { "type": "string" },
166
+ "entity": { "type": "string" },
167
+ "helpText": { "type": "string" },
168
+ "eager": { "type": "boolean", "default": false }
169
+ },
170
+ "additionalProperties": false
171
+ }
172
+ ]
173
+ },
174
+ "accessType": {
175
+ "type": "string",
176
+ "enum": ["public", "restricted", "admin", "forbidden", "🌐", "🔒", "👨🏻‍💻", "🚫"]
177
+ },
178
+ "policy": {
179
+ "type": "object",
180
+ "required": ["access"],
181
+ "properties": {
182
+ "access": { "$ref": "#/$defs/accessType" },
183
+ "allow": {
184
+ "oneOf": [
185
+ { "type": "string" },
186
+ { "type": "array", "items": { "type": "string" } }
187
+ ]
188
+ },
189
+ "condition": { "type": "string", "enum": ["self"] }
190
+ },
191
+ "additionalProperties": false
192
+ },
193
+ "policies": {
194
+ "type": "object",
195
+ "additionalProperties": false,
196
+ "properties": {
197
+ "create": { "type": "array", "items": { "$ref": "#/$defs/policy" } },
198
+ "read": { "type": "array", "items": { "$ref": "#/$defs/policy" } },
199
+ "update": { "type": "array", "items": { "$ref": "#/$defs/policy" } },
200
+ "delete": { "type": "array", "items": { "$ref": "#/$defs/policy" } },
201
+ "signup": { "type": "array", "items": { "$ref": "#/$defs/policy" } }
202
+ }
203
+ },
204
+ "validationRules": {
205
+ "type": "object",
206
+ "properties": {
207
+ "required": { "type": "boolean" },
208
+ "isDefined": { "type": "boolean" },
209
+ "isOptional": { "type": "boolean" },
210
+ "equals": {},
211
+ "notEquals": {},
212
+ "isEmpty": { "type": "boolean" },
213
+ "isNotEmpty": { "type": "boolean" },
214
+ "isIn": { "type": "array" },
215
+ "isNotIn": { "type": "array" },
216
+ "min": { "type": "number" },
217
+ "max": { "type": "number" },
218
+ "contains": { "type": "string" },
219
+ "notContains": { "type": "string" },
220
+ "isAlpha": { "type": "boolean" },
221
+ "isAlphanumeric": { "type": "boolean" },
222
+ "isAscii": { "type": "boolean" },
223
+ "isEmail": { "type": "boolean" },
224
+ "isJSON": { "type": "boolean" },
225
+ "minLength": { "type": "integer" },
226
+ "maxLength": { "type": "integer" },
227
+ "matches": { "type": "string" },
228
+ "isMimeType": { "type": "boolean" }
229
+ },
230
+ "additionalProperties": false
231
+ },
232
+ "lifecycleEvents": {
233
+ "type": "string",
234
+ "enum": ["beforeCreate", "afterCreate", "beforeUpdate", "afterUpdate", "beforeDelete", "afterDelete"]
235
+ },
236
+ "webhook": {
237
+ "type": "object",
238
+ "required": ["url"],
239
+ "properties": {
240
+ "url": { "type": "string", "format": "uri" },
241
+ "method": { "type": "string", "enum": ["GET", "POST", "PUT", "PATCH", "DELETE"], "default": "POST" },
242
+ "headers": { "type": "object", "additionalProperties": { "type": "string" } }
243
+ },
244
+ "additionalProperties": false
245
+ },
246
+ "middleware": {
247
+ "type": "object",
248
+ "required": ["function"],
249
+ "properties": {
250
+ "function": { "type": "string" }
251
+ },
252
+ "additionalProperties": false
253
+ },
254
+ "entity": {
255
+ "type": "object",
256
+ "properties": {
257
+ "authenticable": { "type": "boolean", "default": false, "description": "Makes this entity authenticable (adds email + password fields, enables login/signup)." },
258
+ "single": { "type": "boolean", "default": false, "description": "Single entity — only one record exists (no create/delete)." },
259
+ "mainProp": { "type": "string", "description": "Identifier property used in the admin panel." },
260
+ "nameSingular": { "type": "string" },
261
+ "namePlural": { "type": "string" },
262
+ "seedCount": { "type": "integer", "default": 50 },
263
+ "slug": { "type": "string", "description": "Custom kebab-case slug for API endpoints." },
264
+ "properties": { "type": "array", "items": { "$ref": "#/$defs/property" } },
265
+ "belongsTo": { "type": "array", "items": { "$ref": "#/$defs/relationItem" } },
266
+ "belongsToMany": { "type": "array", "items": { "$ref": "#/$defs/relationItem" } },
267
+ "policies": { "$ref": "#/$defs/policies" },
268
+ "validation": {
269
+ "type": "object",
270
+ "additionalProperties": { "$ref": "#/$defs/validationRules" }
271
+ },
272
+ "hooks": {
273
+ "type": "object",
274
+ "additionalProperties": false,
275
+ "properties": {
276
+ "beforeCreate": { "type": "array", "items": { "$ref": "#/$defs/webhook" } },
277
+ "afterCreate": { "type": "array", "items": { "$ref": "#/$defs/webhook" } },
278
+ "beforeUpdate": { "type": "array", "items": { "$ref": "#/$defs/webhook" } },
279
+ "afterUpdate": { "type": "array", "items": { "$ref": "#/$defs/webhook" } },
280
+ "beforeDelete": { "type": "array", "items": { "$ref": "#/$defs/webhook" } },
281
+ "afterDelete": { "type": "array", "items": { "$ref": "#/$defs/webhook" } }
282
+ }
283
+ },
284
+ "middlewares": {
285
+ "type": "object",
286
+ "additionalProperties": false,
287
+ "properties": {
288
+ "beforeCreate": { "type": "array", "items": { "$ref": "#/$defs/middleware" } },
289
+ "afterCreate": { "type": "array", "items": { "$ref": "#/$defs/middleware" } },
290
+ "beforeUpdate": { "type": "array", "items": { "$ref": "#/$defs/middleware" } },
291
+ "afterUpdate": { "type": "array", "items": { "$ref": "#/$defs/middleware" } },
292
+ "beforeDelete": { "type": "array", "items": { "$ref": "#/$defs/middleware" } },
293
+ "afterDelete": { "type": "array", "items": { "$ref": "#/$defs/middleware" } }
294
+ }
295
+ }
296
+ },
297
+ "additionalProperties": false
298
+ },
299
+ "trigger": {
300
+ "type": "object",
301
+ "required": ["type"],
302
+ "properties": {
303
+ "type": { "type": "string", "enum": ["http", "cron", "event"] },
304
+ "method": { "type": "string", "enum": ["GET", "POST", "PATCH", "PUT", "DELETE"] },
305
+ "path": { "type": "string", "description": "URL path for http triggers (supports :param syntax)." },
306
+ "schedule": { "type": "string", "description": "Cron expression or predefined alias (@daily, @hourly…)." },
307
+ "name": { "type": "string", "description": "Event name for event triggers." },
308
+ "policies": { "type": "array", "items": { "$ref": "#/$defs/policy" }, "description": "Access policies for http triggers. Default: public." }
309
+ },
310
+ "additionalProperties": false
311
+ },
312
+ "endpoint": {
313
+ "type": "object",
314
+ "required": ["function", "triggers"],
315
+ "properties": {
316
+ "function": { "type": "string", "description": "Name of the function file in /functions." },
317
+ "runtime": { "type": "string", "enum": ["js", "bash", "python", "go", "c++", "ruby", "php"], "default": "js" },
318
+ "description": { "type": "string" },
319
+ "triggers": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/trigger" }, "description": "List of triggers (http, cron, event)." }
320
+ },
321
+ "additionalProperties": false
322
+ },
323
+ "group": {
324
+ "type": "object",
325
+ "properties": {
326
+ "properties": { "type": "array", "items": { "$ref": "#/$defs/property" } },
327
+ "validation": {
328
+ "type": "object",
329
+ "additionalProperties": { "$ref": "#/$defs/validationRules" }
330
+ }
331
+ },
332
+ "additionalProperties": false
333
+ },
334
+ "fileBucket": {
335
+ "type": "object",
336
+ "required": ["path"],
337
+ "properties": {
338
+ "path": { "type": "string" },
339
+ "public": { "type": "boolean", "default": false }
340
+ },
341
+ "additionalProperties": false
342
+ },
343
+ "plugin": {
344
+ "type": "object",
345
+ "anyOf": [
346
+ { "required": ["repo"] },
347
+ { "required": ["path"] }
348
+ ],
349
+ "properties": {
350
+ "repo": { "type": "string" },
351
+ "path": { "type": "string" },
352
+ "name": { "type": "string" }
353
+ },
354
+ "additionalProperties": false
355
+ },
356
+ "rateLimit": {
357
+ "type": "object",
358
+ "required": ["name", "limit", "ttl"],
359
+ "additionalProperties": false,
360
+ "properties": {
361
+ "name": { "type": "string", "description": "Identifier for this rate limit definition." },
362
+ "limit": { "type": "integer", "description": "Maximum number of requests allowed in the time window." },
363
+ "ttl": { "type": "integer", "description": "Time window in milliseconds." }
364
+ }
365
+ }
366
+ }
367
+ }
package/chadstart.yaml ADDED
@@ -0,0 +1,53 @@
1
+ name: Blog
2
+
3
+ port: 3000
4
+
5
+ entities:
6
+ Admin:
7
+ authenticable: true
8
+ properties:
9
+ - name
10
+
11
+ Customer:
12
+ authenticable: true
13
+ properties:
14
+ - name
15
+ - phone
16
+
17
+ Post:
18
+ properties:
19
+ - title
20
+ - { name: content, type: text }
21
+ - { name: published, type: boolean }
22
+ policies:
23
+ create:
24
+ - { access: restricted, allow: Admin }
25
+ read:
26
+ - access: public
27
+ update:
28
+ - { access: restricted, allow: Admin }
29
+ delete:
30
+ - { access: restricted, allow: Admin }
31
+
32
+ Comment:
33
+ properties:
34
+ - text
35
+ belongsTo:
36
+ - Post
37
+ policies:
38
+ create:
39
+ - access: restricted
40
+ read:
41
+ - access: public
42
+ update:
43
+ - access: restricted
44
+ delete:
45
+ - access: restricted
46
+
47
+ files:
48
+ uploads:
49
+ path: ./uploads
50
+ public: true
51
+
52
+ public:
53
+ folder: ./public