@nocobase/app-template-default 0.0.0-stage → 1.0.0-beta.58

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 (249) hide show
  1. package/.cursor/mcp.json +8 -0
  2. package/.mcp.json +8 -0
  3. package/.prettierignore +20 -0
  4. package/.vscode/mcp.json +8 -0
  5. package/AGENTS.md +434 -0
  6. package/CLAUDE.md +9 -0
  7. package/Dockerfile +132 -0
  8. package/Dockerfile.dockerignore +45 -0
  9. package/README.MD +485 -0
  10. package/cli/plugins.ts +8 -0
  11. package/client/agent-annotations-host.ts +19 -0
  12. package/client/app.ts +38 -0
  13. package/client/components/back-button.tsx +49 -0
  14. package/client/components/breadcrumbs.tsx +167 -0
  15. package/client/components/inbox-badge.ts +49 -0
  16. package/client/components/inbox-button.tsx +132 -0
  17. package/client/components/inbox-header-button.tsx +25 -0
  18. package/client/components/loading.tsx +35 -0
  19. package/client/components/page-container.tsx +24 -0
  20. package/client/components/page-header.tsx +33 -0
  21. package/client/components/route-child-page.tsx +121 -0
  22. package/client/components/route-dialog.tsx +10 -0
  23. package/client/components/route-drawer.tsx +10 -0
  24. package/client/components/route-overlay.tsx +190 -0
  25. package/client/components/ui/alert.tsx +75 -0
  26. package/client/components/ui/badge.tsx +51 -0
  27. package/client/components/ui/breadcrumb.tsx +121 -0
  28. package/client/components/ui/button.tsx +58 -0
  29. package/client/components/ui/collapsible.tsx +19 -0
  30. package/client/components/ui/context-menu.tsx +271 -0
  31. package/client/components/ui/dialog.tsx +160 -0
  32. package/client/components/ui/dropdown-menu.tsx +270 -0
  33. package/client/components/ui/empty.tsx +103 -0
  34. package/client/components/ui/field.tsx +236 -0
  35. package/client/components/ui/input-group.tsx +158 -0
  36. package/client/components/ui/input.tsx +20 -0
  37. package/client/components/ui/kbd.tsx +26 -0
  38. package/client/components/ui/label.tsx +18 -0
  39. package/client/components/ui/popover.tsx +89 -0
  40. package/client/components/ui/select.tsx +200 -0
  41. package/client/components/ui/separator.tsx +22 -0
  42. package/client/components/ui/sheet.tsx +137 -0
  43. package/client/components/ui/sidebar.tsx +723 -0
  44. package/client/components/ui/skeleton.tsx +13 -0
  45. package/client/components/ui/spinner.tsx +20 -0
  46. package/client/components/ui/tabs.tsx +79 -0
  47. package/client/components/ui/textarea.tsx +17 -0
  48. package/client/components/ui/toast.tsx +231 -0
  49. package/client/components/ui/tooltip.tsx +63 -0
  50. package/client/components/use-route-overlay.ts +26 -0
  51. package/client/config/api.ts +13 -0
  52. package/client/config/app.ts +8 -0
  53. package/client/config/auth.ts +18 -0
  54. package/client/config/index.ts +17 -0
  55. package/client/extensions/nocobase-auth-forms/field-props.ts +13 -0
  56. package/client/extensions/nocobase-auth-forms/form-parts.tsx +101 -0
  57. package/client/extensions/nocobase-auth-forms/password-input.tsx +41 -0
  58. package/client/extensions/nocobase-auth-forms/password-login-form.tsx +123 -0
  59. package/client/extensions/nocobase-auth-forms/password-registration-form.tsx +193 -0
  60. package/client/extensions/nocobase-auth-forms/password-reset-form.tsx +132 -0
  61. package/client/extensions/nocobase-auth-forms/password-reset-request-form.tsx +99 -0
  62. package/client/extensions/nocobase-auth-methods/auth-methods.tsx +170 -0
  63. package/client/extensions/nocobase-auth-split-layout/auth-split-layout.tsx +126 -0
  64. package/client/extensions/nocobase-device-approval/device-approval.tsx +277 -0
  65. package/client/extensions/nocobase-device-approval/locales/en-US.ts +55 -0
  66. package/client/extensions/nocobase-device-approval/locales/zh-CN.ts +27 -0
  67. package/client/extensions/nocobase-device-approval/use-device-approval.ts +176 -0
  68. package/client/extensions/nocobase-file-component-ui/README.md +13 -0
  69. package/client/extensions/nocobase-file-component-ui/components/file-list.tsx +147 -0
  70. package/client/extensions/nocobase-file-component-ui/components/file-preview-dialog.tsx +263 -0
  71. package/client/extensions/nocobase-file-component-ui/components/file-preview-field.tsx +68 -0
  72. package/client/extensions/nocobase-file-component-ui/components/file-thumbnail.tsx +73 -0
  73. package/client/extensions/nocobase-file-component-ui/components/file-upload-field.tsx +386 -0
  74. package/client/extensions/nocobase-file-component-ui/components/previewers/file-preview-content.tsx +255 -0
  75. package/client/extensions/nocobase-file-component-ui/components/previewers/office-open-xml-preview.tsx +226 -0
  76. package/client/extensions/nocobase-file-component-ui/index.ts +8 -0
  77. package/client/extensions/nocobase-file-component-ui/lib/file-preview.ts +194 -0
  78. package/client/extensions/nocobase-file-component-ui/lib/file-url.ts +22 -0
  79. package/client/extensions/nocobase-file-component-ui/lib/message-key.ts +18 -0
  80. package/client/extensions/nocobase-file-component-ui/types.ts +69 -0
  81. package/client/extensions/nocobase-inbox/decision-actions-bar.tsx +140 -0
  82. package/client/extensions/nocobase-inbox/frame.ts +31 -0
  83. package/client/extensions/nocobase-inbox/inbox-actions.ts +21 -0
  84. package/client/extensions/nocobase-inbox/inbox-detail.tsx +386 -0
  85. package/client/extensions/nocobase-inbox/inbox-item.tsx +274 -0
  86. package/client/extensions/nocobase-inbox/inbox-list.tsx +433 -0
  87. package/client/extensions/nocobase-inbox/inbox-page.tsx +545 -0
  88. package/client/extensions/nocobase-inbox/locales/en-US.ts +111 -0
  89. package/client/extensions/nocobase-inbox/locales/zh-CN.ts +57 -0
  90. package/client/extensions/nocobase-inbox/model.ts +428 -0
  91. package/client/extensions/nocobase-inbox/registry-scope.tsx +49 -0
  92. package/client/extensions/nocobase-inbox/registry.ts +303 -0
  93. package/client/extensions/nocobase-inbox/source.ts +117 -0
  94. package/client/hooks/use-mobile.ts +21 -0
  95. package/client/index.tsx +60 -0
  96. package/client/layouts/app-layout.tsx +105 -0
  97. package/client/layouts/components/app-brand.tsx +49 -0
  98. package/client/layouts/components/app-sidebar.tsx +196 -0
  99. package/client/layouts/components/header-actions.tsx +50 -0
  100. package/client/layouts/components/language-switcher.tsx +95 -0
  101. package/client/layouts/components/layout-header.tsx +17 -0
  102. package/client/layouts/components/navigation-menu.tsx +411 -0
  103. package/client/layouts/components/sidebar-footer.tsx +107 -0
  104. package/client/layouts/components/surface-empty.tsx +35 -0
  105. package/client/layouts/components/user-menu.tsx +127 -0
  106. package/client/layouts/index.ts +2 -0
  107. package/client/layouts/settings-layout.tsx +172 -0
  108. package/client/layouts/use-sidebar-preference.ts +57 -0
  109. package/client/lib/constants.ts +5 -0
  110. package/client/lib/toaster.ts +56 -0
  111. package/client/lib/utils.ts +1 -0
  112. package/client/locales/en-US.ts +178 -0
  113. package/client/locales/index.ts +9 -0
  114. package/client/locales/zh-CN.ts +161 -0
  115. package/client/pages/auth/device.tsx +41 -0
  116. package/client/pages/auth/forgot-password.tsx +39 -0
  117. package/client/pages/auth/login.tsx +66 -0
  118. package/client/pages/auth/register.tsx +46 -0
  119. package/client/pages/auth/reset-password.tsx +38 -0
  120. package/client/pages/auth/shared.tsx +111 -0
  121. package/client/pages/home.tsx +16 -0
  122. package/client/pages/inbox.tsx +12 -0
  123. package/client/plugins.ts +37 -0
  124. package/client/react-providers.ts +27 -0
  125. package/client/route-overrides.ts +9 -0
  126. package/client/routes.ts +75 -0
  127. package/client/routing/app-router.tsx +127 -0
  128. package/client/routing/client-route.tsx +129 -0
  129. package/client/routing/route-context.tsx +85 -0
  130. package/client/routing/route-navigation.ts +153 -0
  131. package/client/routing/route-tree.tsx +42 -0
  132. package/client/routing/standalone-page-layout.tsx +15 -0
  133. package/client/runtime.ts +26 -0
  134. package/client/service-provider.ts +40 -0
  135. package/client/source-extensions.ts +19 -0
  136. package/client/startup.tsx +22 -0
  137. package/client/styles.css +122 -0
  138. package/client/theme/index.ts +4 -0
  139. package/client/theme/theme-context.ts +12 -0
  140. package/client/theme/theme-preferences.ts +84 -0
  141. package/client/theme/theme-presets.ts +7 -0
  142. package/client/theme/theme-provider.tsx +106 -0
  143. package/client/theme/theme-settings.tsx +176 -0
  144. package/client/theme/themes/compact.css +140 -0
  145. package/client/theme/themes/default.css +117 -0
  146. package/client/vite-env.d.ts +5 -0
  147. package/components.json +27 -0
  148. package/config.example.yml +156 -0
  149. package/database/main/migrations/.gitkeep +0 -0
  150. package/database/main/migrations/202610060001_create_device_code.ts +37 -0
  151. package/database/main/seeds/.gitkeep +0 -0
  152. package/database/tsconfig.json +4 -0
  153. package/ecosystem.config.js +35 -0
  154. package/eslint.config.js +24 -0
  155. package/index.html +100 -0
  156. package/package.json +198 -3
  157. package/playwright.config.ts +10 -0
  158. package/public/assets/favicon.ico +0 -0
  159. package/public/assets/logo-dark.png +0 -0
  160. package/public/assets/logo-mark-dark.png +0 -0
  161. package/public/assets/logo-mark.png +0 -0
  162. package/public/assets/logo.png +0 -0
  163. package/server/app.ts +50 -0
  164. package/server/config/api.ts +8 -0
  165. package/server/config/app.ts +40 -0
  166. package/server/config/auth.ts +36 -0
  167. package/server/config/authorization.ts +18 -0
  168. package/server/config/caching.ts +21 -0
  169. package/server/config/database.ts +22 -0
  170. package/server/config/drive.ts +30 -0
  171. package/server/config/i18n.ts +17 -0
  172. package/server/config/index.ts +67 -0
  173. package/server/config/jobs.ts +27 -0
  174. package/server/config/logging.ts +23 -0
  175. package/server/config/notification.ts +11 -0
  176. package/server/config/queue.ts +28 -0
  177. package/server/config/scheduler.ts +23 -0
  178. package/server/config/secrets.ts +10 -0
  179. package/server/config/server.ts +26 -0
  180. package/server/config/session.ts +60 -0
  181. package/server/config/snowflake.ts +21 -0
  182. package/server/config/spa.ts +24 -0
  183. package/server/config/users.ts +11 -0
  184. package/server/config/workflow.ts +24 -0
  185. package/server/config.ts +24 -0
  186. package/server/embedded.ts +23 -0
  187. package/server/locales/en-US.ts +10 -0
  188. package/server/locales/index.ts +10 -0
  189. package/server/locales/zh-CN.ts +5 -0
  190. package/server/plugins.ts +37 -0
  191. package/server/providers/index.ts +5 -0
  192. package/server/routes/index.ts +6 -0
  193. package/server/runtime.ts +24 -0
  194. package/server/standalone.ts +29 -0
  195. package/server/tsconfig.json +4 -0
  196. package/tailwind.config.mjs +59 -0
  197. package/tests/components/app-layout-routes.test.tsx +132 -0
  198. package/tests/components/app-title.test.tsx +57 -0
  199. package/tests/components/auth-i18n.test.tsx +87 -0
  200. package/tests/components/back-button.test.tsx +80 -0
  201. package/tests/components/file-preview.test.tsx +101 -0
  202. package/tests/components/header-hover.test.tsx +87 -0
  203. package/tests/components/inbox.test.tsx +139 -0
  204. package/tests/components/language-switcher.test.tsx +298 -0
  205. package/tests/components/layout-containers.test.tsx +15 -0
  206. package/tests/components/layout-i18n.test.tsx +187 -0
  207. package/tests/components/loading.test.tsx +25 -0
  208. package/tests/components/navigation-menu.test.tsx +355 -0
  209. package/tests/components/page-harness.test.tsx +318 -0
  210. package/tests/components/primitive-labels.test.tsx +80 -0
  211. package/tests/components/sidebar-permissions.test.tsx +110 -0
  212. package/tests/components/sidebar-preference.test.tsx +42 -0
  213. package/tests/fixtures/theme-tokens.html +12 -0
  214. package/tests/fixtures/theme-tokens.tsx +111 -0
  215. package/tests/logic/account-permissions.test.tsx +204 -0
  216. package/tests/logic/app-locale-coverage.test.ts +136 -0
  217. package/tests/logic/app-server.test.ts +1589 -0
  218. package/tests/logic/asset-url-build.test.ts +106 -0
  219. package/tests/logic/client-auth.test.tsx +122 -0
  220. package/tests/logic/client-plugin-registry.test.ts +63 -0
  221. package/tests/logic/client-route-recovery.test.tsx +80 -0
  222. package/tests/logic/client-routes.test.ts +126 -0
  223. package/tests/logic/client-runtime.test.ts +112 -0
  224. package/tests/logic/client-settings.test.tsx +841 -0
  225. package/tests/logic/client-shell.test.tsx +466 -0
  226. package/tests/logic/client-theme.test.tsx +441 -0
  227. package/tests/logic/config.test.ts +197 -0
  228. package/tests/logic/dev-client-watch.test.ts +108 -0
  229. package/tests/logic/dev-routes-production-build.test.ts +168 -0
  230. package/tests/logic/device-code-migration.test.ts +70 -0
  231. package/tests/logic/lifecycle.test.ts +221 -0
  232. package/tests/logic/plugin-commands.test.ts +69 -0
  233. package/tests/logic/plugin-page-authz.test.ts +53 -0
  234. package/tests/logic/route-navigation.test.ts +66 -0
  235. package/tests/logic/route-overlay.test.tsx +353 -0
  236. package/tests/logic/server-imports.test.ts +88 -0
  237. package/tests/logic/tailwind-sources.test.ts +151 -0
  238. package/tests/logic/template-package-name.test.ts +88 -0
  239. package/tests/logic/theme-preferences.test.ts +86 -0
  240. package/tests/logic/theme-tokens.test.ts +248 -0
  241. package/tests/logic/toaster.test.tsx +108 -0
  242. package/tests/logic/user-menu-sign-out.test.tsx +98 -0
  243. package/tests/setup/client-config.ts +27 -0
  244. package/tsconfig.json +11 -0
  245. package/tsconfig.node.json +12 -0
  246. package/tsconfig.server.json +19 -0
  247. package/vite.config.ts +92 -0
  248. package/vitest.config.ts +44 -0
  249. package/README.md +0 -3
@@ -0,0 +1,156 @@
1
+ # Copy this file to config.yml before starting the application.
2
+
3
+ # app:
4
+ # Public origin used for callbacks and redirects in production.
5
+ # publicOrigin: https://apps.example.com
6
+
7
+ # The language the application starts in, for the browser and the server alike. Which languages it offers follows
8
+ # from the files in client/locales and server/locales, not from configuration.
9
+ # i18n:
10
+ # defaultLocale: zh-CN
11
+
12
+ # Limits every /api request meets before its route, each off until set. bodyLimit refuses a larger body with 413
13
+ # BODY_TOO_LARGE; a route may set its own, usually smaller, limit. timeout answers 503 REQUEST_TIMEOUT when a handler
14
+ # has not produced its response in time; a streaming response that has started is not cut off. rateLimit allows max
15
+ # requests per window from each client address and answers 429 RATE_LIMITED with Retry-After; GET /api/healthz is
16
+ # exempt. Counters live in each process, so every instance counts on its own, and behind a reverse proxy the proxy is
17
+ # the client address. API_BODY_LIMIT and API_TIMEOUT set the first two.
18
+ # api:
19
+ # bodyLimit: 10mb
20
+ # timeout: 30s
21
+ # rateLimit:
22
+ # max: 600
23
+ # window: 1m
24
+
25
+ # Values under client are public and embedded in the SPA HTML.
26
+ client:
27
+ app:
28
+ title: NocoBase
29
+ # Defaults apply only when no valid browser-local choice is saved.
30
+ # defaultColorScheme: system # light | dark | system
31
+ # defaultTheme: compact # ID from client/theme/theme-presets.ts
32
+
33
+ users:
34
+ # The first administrator, created only when seeding an empty user table. Changing these values later does not
35
+ # reset an existing account. Replace the password before exposing the application. INITIAL_ADMIN_USERNAME,
36
+ # INITIAL_ADMIN_EMAIL and INITIAL_ADMIN_PASSWORD set them from the environment instead.
37
+ initialAdmin:
38
+ username: nocobase # 3–30 letters, digits, underscores or dots; stored lowercase
39
+ email: admin@nocobase.com # stored lowercase; also signs in
40
+ password: admin123
41
+
42
+ # Master keys for what the application encrypts at rest — stored credentials and API keys, OAuth tokens — and from
43
+ # which the sign-in and session keys are derived. The first key is current; the others only decrypt. To rotate, put a
44
+ # new key first with a higher version, run `pnpm nocobase secrets rotate`, then remove the old key. Changing the current
45
+ # key signs everyone out. Generate a key with: openssl rand -hex 32. SECRETS_KEYS=2:<key>,1:<key> sets the list from
46
+ # the environment instead.
47
+ secrets:
48
+ keys:
49
+ - version: 1
50
+ key: replace-with-a-unique-secret
51
+
52
+ auth:
53
+ emailAndPassword:
54
+ enabled: true
55
+ autoSignIn: false
56
+ session:
57
+ storeSessionInDatabase: true
58
+
59
+ notification:
60
+ channels:
61
+ inbox:
62
+ provider: in-app
63
+
64
+ # Uncomment and configure independent email Channels.
65
+ # Values are read as written: ${NAME} is not expanded. To take a secret from the environment instead, map a
66
+ # variable onto its path in env of server/config/notification.ts, such as SMTP_PASSWORD.
67
+ # system-email:
68
+ # provider: smtp
69
+ # host: smtp.example.com
70
+ # port: 587
71
+ # auth:
72
+ # user: notifications@example.com
73
+ # pass: replace-with-the-smtp-password
74
+ # from: notifications@example.com
75
+ # marketing-email:
76
+ # provider: resend
77
+ # apiKey: replace-with-the-resend-api-key
78
+ # from: marketing@example.com
79
+
80
+ # ops-feishu:
81
+ # provider: feishu-webhook
82
+ # webhookUrl: https://open.feishu.cn/open-apis/bot/v2/hook/replace-with-the-token
83
+ # ops-dingtalk:
84
+ # provider: dingtalk-webhook
85
+ # webhookUrl: https://oapi.dingtalk.com/robot/send?access_token=replace-with-the-token
86
+
87
+ # DB_DIALECT, DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, DB_PASSWORD, DB_SSL and DB_FILENAME override the main
88
+ # connection's fields from the environment.
89
+ database:
90
+ default: main
91
+ connections:
92
+ main:
93
+ dialect: sqlite
94
+ database: database.sqlite
95
+ debug: false
96
+ # For Oracle, use dialect: oracle and replace database with serviceName: FREEPDB1.
97
+ # For SQL Server, use dialect: mssql and configure encrypt and trustServerCertificate.
98
+ schemaManagement: managed
99
+ migrations:
100
+ autoRun: true
101
+ seeds:
102
+ autoRun: true
103
+ # Additional managed databases use database/<connectionName>/{migrations,seeds}.
104
+ # analytics:
105
+ # dialect: postgres
106
+ # host: localhost
107
+ # database: analytics
108
+ # username: postgres
109
+ # password: replace-with-the-password # or DB_ANALYTICS_PASSWORD, declared with connectionEnvironment('analytics', 'DB_ANALYTICS')
110
+ # schemaManagement: managed
111
+ # migrations:
112
+ # autoRun: false
113
+ # seeds:
114
+ # autoRun: false
115
+ # An existing database another system owns sets schemaManagement: external and runs no tasks. Its titles,
116
+ # descriptions and relations are read from database/<connection>/metadata/<name>.json unless metadataStore says otherwise.
117
+
118
+ snowflake:
119
+ # Assign a unique worker ID to each concurrently running instance.
120
+ workerId: 0
121
+ epoch: 1605024000
122
+
123
+ # Scheduled jobs, such as the Scheduler plugin's. Without jobs.default they run on the built-in memory adapter:
124
+ # state kept in the process, read from storage/jobs at startup and written back when the application stops, so a
125
+ # process that is killed loses what changed since it started. It serves one process: every other process or instance
126
+ # would run its own copy. Set default to memory to keep that without the startup warning, or to redis to run several.
127
+ # Redis must persist its data (AOF or RDB) and use maxmemory-policy noeviction, or schedules can be lost.
128
+ # jobs:
129
+ # default: redis
130
+ # redis:
131
+ # connection:
132
+ # host: 127.0.0.1
133
+ # port: 6379
134
+ # # namespace: my-app # defaults to the application name; set it when deployments share one Redis
135
+
136
+ # The jobs configuration the Scheduler plugin's schedules run on, by name. Left out, they follow jobs.default.
137
+ # scheduler:
138
+ # jobs: redis
139
+
140
+ # File logging is independent of terminal formatting.
141
+ logging:
142
+ level: info
143
+ file:
144
+ enabled: true
145
+ retentionDays: 7
146
+ name: app
147
+ maxFileSizeMB: 10
148
+ maxTotalSizeMB: 500
149
+ loggers:
150
+ request:
151
+ file:
152
+ name: request
153
+ console:
154
+ enabled: true
155
+ # Set true for human-readable terminal output.
156
+ pretty: false
File without changes
@@ -0,0 +1,37 @@
1
+ import { defineMigration, type MigrationDefinition } from '@nocobase/db';
2
+
3
+ /**
4
+ * Creates the `deviceCode` table Better Auth's `deviceAuthorization()` plugin reads and writes: a CLI's sign-in
5
+ * through the browser (RFC 8628). The shape is the plugin's schema in better-auth 1.7.5, spelled out here so a later
6
+ * release cannot change what this migration did; when that schema gains a field, add it in a new migration.
7
+ *
8
+ * `pollingInterval` is milliseconds. A row lives until its code is redeemed, denied or found expired.
9
+ */
10
+ const migration: MigrationDefinition = defineMigration({
11
+ name: '202610060001_create_device_code',
12
+
13
+ async up({ builder }) {
14
+ await builder.createCollection('deviceCode', (collection) => {
15
+ collection.string('id', { length: 64 }).notNull();
16
+ collection.string('deviceCode', { length: 191 }).notNull();
17
+ collection.string('userCode', { length: 191 }).notNull();
18
+ collection.string('userId', { length: 64 }).nullable();
19
+ collection.datetime('expiresAt').notNull();
20
+ collection.string('status', { length: 32 }).notNull();
21
+ collection.datetime('lastPolledAt').nullable();
22
+ collection.integer('pollingInterval').nullable();
23
+ collection.string('clientId', { length: 255 }).nullable();
24
+ collection.text('scope').nullable();
25
+
26
+ collection.primary('id', { name: 'pk_device_code' });
27
+ collection.unique('deviceCode', { name: 'uq_device_code_device_code' });
28
+ collection.unique('userCode', { name: 'uq_device_code_user_code' });
29
+ });
30
+ },
31
+
32
+ async down({ builder }) {
33
+ await builder.dropCollection('deviceCode');
34
+ },
35
+ });
36
+
37
+ export default migration;
File without changes
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "../tsconfig.server.json",
3
+ "include": ["**/*.ts"]
4
+ }
@@ -0,0 +1,35 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ // The pm2 process name. `APP_PM2_NAME` chooses it; otherwise it follows the application's package name, read from the
5
+ // project root or, beside an unpacked deployment archive, from `dist/package.json`. Two applications on one machine
6
+ // then get different names: pm2 treats `pm2 start` on a name it already runs as a restart of that process.
7
+ const manifest = ['package.json', 'dist/package.json']
8
+ .map((file) => path.join(import.meta.dirname, file))
9
+ .find((file) => existsSync(file));
10
+ const packageName = manifest
11
+ ? JSON.parse(readFileSync(manifest, 'utf8')).name
12
+ : undefined;
13
+ const name =
14
+ process.env.APP_PM2_NAME ||
15
+ `nocobase-${String(packageName ?? 'app').replace(/^@[^/]+\//, '')}`;
16
+
17
+ export const apps = [
18
+ {
19
+ name,
20
+ // pm2's fork mode loads a script through its own wrapper, so
21
+ // import.meta.main is false there and standalone.js never starts the
22
+ // server. Running node itself keeps standalone.js the main module.
23
+ script: 'node',
24
+ args: './dist/server/standalone.js',
25
+ // Resolve `args` against this file's directory rather than wherever
26
+ // `pm2 start` runs, so the path to this file can be given from anywhere.
27
+ cwd: import.meta.dirname,
28
+ interpreter: 'none',
29
+ env: {
30
+ NODE_ENV: 'production',
31
+ },
32
+ },
33
+ ];
34
+
35
+ export default { apps };
@@ -0,0 +1,24 @@
1
+ import { createApplicationConfig } from '@nocobase/dev-config/eslint';
2
+
3
+ export default createApplicationConfig({
4
+ tsconfigRootDir: import.meta.dirname,
5
+ ignores: [
6
+ '.extension-state/**',
7
+ 'client-old/**',
8
+ 'public/r/**',
9
+ 'storage/**',
10
+ ],
11
+ overrides: [
12
+ {
13
+ // Top-level workflow definitions and handlers use the server project.
14
+ files: ['workflows/**/*.ts'],
15
+ ignores: ['workflows/*/client/**'],
16
+ languageOptions: {
17
+ parserOptions: {
18
+ projectService: false,
19
+ project: './tsconfig.server.json',
20
+ },
21
+ },
22
+ },
23
+ ],
24
+ });
package/index.html ADDED
@@ -0,0 +1,100 @@
1
+ <!doctype html>
2
+ <html lang="en-US">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <link rel="icon" type="image/x-icon" href="/assets/favicon.ico" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ <meta name="theme-color" content="#171717" />
8
+ <meta name="description" content="NocoBase administration console" />
9
+ <meta data-rh="true" property="og:image" content="/assets/logo-mark.png" />
10
+ <meta data-rh="true" name="twitter:image" content="/assets/logo-mark.png" />
11
+ <style>
12
+ .app-bootstrap-loading {
13
+ display: flex;
14
+ min-height: 100svh;
15
+ width: 100%;
16
+ align-items: center;
17
+ justify-content: center;
18
+ background: oklch(0.985 0 0);
19
+ color: oklch(0.18 0 0);
20
+ }
21
+
22
+ .app-bootstrap-loading [data-slot='loading-indicator'] {
23
+ width: 1.75rem;
24
+ height: 1.75rem;
25
+ opacity: 0;
26
+ animation:
27
+ app-bootstrap-reveal 0s 200ms forwards,
28
+ app-bootstrap-spin 1s linear 200ms infinite;
29
+ }
30
+
31
+ html,
32
+ body {
33
+ margin: 0;
34
+ }
35
+
36
+ @keyframes app-bootstrap-spin {
37
+ to {
38
+ transform: rotate(360deg);
39
+ }
40
+ }
41
+
42
+ @keyframes app-bootstrap-reveal {
43
+ to {
44
+ opacity: 1;
45
+ }
46
+ }
47
+
48
+ @media (prefers-color-scheme: dark) {
49
+ .app-bootstrap-loading {
50
+ background: oklch(0.145 0 0);
51
+ color: oklch(0.9 0 0);
52
+ }
53
+ }
54
+
55
+ @media (prefers-reduced-motion: reduce) {
56
+ .app-bootstrap-loading [data-slot='loading-indicator'] {
57
+ animation: none;
58
+ opacity: 0.65;
59
+ }
60
+ }
61
+ </style>
62
+ <title>NocoBase</title>
63
+ </head>
64
+ <body>
65
+ <noscript>You need to enable JavaScript to run this app.</noscript>
66
+ <div id="root">
67
+ <div
68
+ class="app-bootstrap-loading"
69
+ role="status"
70
+ aria-label="Loading application"
71
+ >
72
+ <svg
73
+ data-slot="loading-indicator"
74
+ viewBox="0 0 24 24"
75
+ fill="none"
76
+ aria-hidden="true"
77
+ >
78
+ <path
79
+ d="M21 12a9 9 0 1 1-6.219-8.56"
80
+ stroke="currentColor"
81
+ stroke-width="2"
82
+ stroke-linecap="round"
83
+ stroke-linejoin="round"
84
+ />
85
+ </svg>
86
+ </div>
87
+ </div>
88
+ <script type="module" src="/client/index.tsx"></script>
89
+ <!--
90
+ This HTML file is a template.
91
+ If you open it directly in the browser, you will see an empty page.
92
+
93
+ You can add webfonts, meta tags, or analytics to this file.
94
+ The build step will place the bundled scripts into the <body> tag.
95
+
96
+ To begin development, run `pnpm dev`.
97
+ To create a production bundle, run `pnpm build`.
98
+ -->
99
+ </body>
100
+ </html>
package/package.json CHANGED
@@ -1,6 +1,201 @@
1
1
  {
2
2
  "name": "@nocobase/app-template-default",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "displayName": "Default Template",
4
+ "version": "1.0.0-beta.58",
5
+ "type": "module",
6
+ "prettier": "@nocobase/dev-config/prettier",
7
+ "engines": {
8
+ "node": ">=24.0.0"
9
+ },
10
+ "nocobase": {
11
+ "templateKind": "app",
12
+ "defaultTemplateVersion": "1.0.0-beta.58"
13
+ },
14
+ "devDependencies": {
15
+ "@ai-sdk/react": "2.0.0",
16
+ "@base-ui/react": "^1.6.0",
17
+ "@dicebear/core": "^9.4.3",
18
+ "@gchust/agent-annotations": "0.1.9",
19
+ "@hookform/resolvers": "^5.0.1",
20
+ "@nocobase/ai-employee-avatars": "^1.0.2",
21
+ "@playwright/test": "^1.62.1",
22
+ "@refinedev/cli": "^2.16.48",
23
+ "@refinedev/core": "^5.0.8",
24
+ "@refinedev/react-hook-form": "^5.0.0",
25
+ "@refinedev/react-router": "^2.0.0",
26
+ "@refinedev/react-table": "^6.0.0",
27
+ "@silurus/ooxml": "0.85.1",
28
+ "@tailwindcss/postcss": "^4.1.4",
29
+ "@tailwindcss/vite": "^4.1.8",
30
+ "@tanstack/react-query": "^5.81.5",
31
+ "@testing-library/jest-dom": "^7.0.0",
32
+ "@testing-library/react": "^16.3.2",
33
+ "@testing-library/user-event": "^14.6.3",
34
+ "@tiptap/core": "3.30.2",
35
+ "@tiptap/extension-link": "3.30.2",
36
+ "@tiptap/extension-placeholder": "3.30.2",
37
+ "@tiptap/extension-text-style": "3.30.2",
38
+ "@tiptap/pm": "3.30.2",
39
+ "@tiptap/react": "3.30.2",
40
+ "@tiptap/starter-kit": "3.30.2",
41
+ "@types/node": "^24.0.0",
42
+ "@types/react": "^19.2.0",
43
+ "@types/react-dom": "^19.2.0",
44
+ "@vitejs/plugin-react": "^4.4.1",
45
+ "@vitest/coverage-v8": "^4.1.10",
46
+ "ai": "5.0.0",
47
+ "class-variance-authority": "^0.7.1",
48
+ "cn": "^0.4.0",
49
+ "dayjs": "^1.10.7",
50
+ "dingtalk-jsapi": "3.1.1",
51
+ "echarts": "^5.5.0",
52
+ "echarts-for-react": "3.0.2",
53
+ "eslint": "^10.0.0",
54
+ "eventsource-parser": "3.1.0",
55
+ "ignore": "^7.0.6",
56
+ "jsdom": "^30.0.1",
57
+ "knex": "^3.1.0",
58
+ "lucide-react": "^0.487.0",
59
+ "next-themes": "^0.4.6",
60
+ "postcss": "^8.5.3",
61
+ "prettier": "^3.9.6",
62
+ "react": "^19.2.8",
63
+ "react-dom": "^19.2.8",
64
+ "react-error-boundary": "^6.0.0",
65
+ "react-hook-form": "^7.57.0",
66
+ "react-i18next": "^17.0.12",
67
+ "react-markdown": "^10.1.0",
68
+ "react-router": "^7.0.2",
69
+ "remark-gfm": "^4.0.1",
70
+ "shadcn": "^4.13.1",
71
+ "tailwindcss": "^4.1.4",
72
+ "tsc-alias": "^1.9.2",
73
+ "tsx": "^4.21.0",
74
+ "tw-animate-css": "^1.2.5",
75
+ "typescript": "^6.0.3",
76
+ "vite": "^6.3.5",
77
+ "vitest": "^4.1.10",
78
+ "tar": "^7.5.22",
79
+ "@nocobase/app-client": "^2.0.0-beta.2",
80
+ "@nocobase/app-plugin-template-print": "0.0.2-beta.1",
81
+ "@nocobase/app-skills": "0.1.0-beta.26",
82
+ "@nocobase/app-testing": "0.1.0-beta.1",
83
+ "@nocobase/app-websocket": "^0.0.1",
84
+ "@nocobase/dev-config": "0.1.0-beta.20",
85
+ "@nocobase/drive": "^0.1.0-beta.4",
86
+ "@nocobase/hub-cli": "^1.0.0-beta.2",
87
+ "@nocobase/logging": "^0.1.0-beta.6",
88
+ "@nocobase/session": "^0.1.0-beta.2"
89
+ },
90
+ "files": [
91
+ ".prettierignore",
92
+ ".mcp.json",
93
+ ".cursor/mcp.json",
94
+ ".vscode/mcp.json",
95
+ "cli",
96
+ "client",
97
+ "server",
98
+ "workflows",
99
+ "database/tsconfig.json",
100
+ "database/*/migrations/**",
101
+ "database/*/seeds/**",
102
+ "public",
103
+ "tests",
104
+ "index.html",
105
+ "components.json",
106
+ "tailwind.config.mjs",
107
+ "vite.config.ts",
108
+ "vitest.config.ts",
109
+ "eslint.config.js",
110
+ "tsconfig.json",
111
+ "tsconfig.node.json",
112
+ "tsconfig.server.json",
113
+ "ecosystem.config.js",
114
+ "Dockerfile",
115
+ "Dockerfile.dockerignore",
116
+ "config.example.yml",
117
+ "README.MD",
118
+ "AGENTS.md",
119
+ "CLAUDE.md",
120
+ "playwright.config.ts"
121
+ ],
122
+ "publishConfig": {
123
+ "access": "public"
124
+ },
125
+ "repository": {
126
+ "type": "git",
127
+ "url": "git+https://github.com/nocobase/nocobase.git",
128
+ "directory": "packages/templates/app-template-default"
129
+ },
130
+ "browserslist": {
131
+ "production": [
132
+ ">0.2%",
133
+ "not dead",
134
+ "not op_mini all"
135
+ ],
136
+ "development": [
137
+ "last 1 chrome version",
138
+ "last 1 firefox version",
139
+ "last 1 safari version"
140
+ ]
141
+ },
142
+ "dependencies": {
143
+ "zod": "^4.6.5",
144
+ "@oclif/core": "^4.14.0",
145
+ "better-auth": "1.7.5",
146
+ "hono": "^4.13.2",
147
+ "@nocobase/app-plugin-api-keys": "^1.0.0-beta.13",
148
+ "@nocobase/app-plugin-authentication": "^2.0.0-beta.2",
149
+ "@nocobase/app-plugin-authorization": "^1.0.0-beta.25",
150
+ "@nocobase/app-plugin-database-explorer": "^1.0.0-beta.11",
151
+ "@nocobase/app-plugin-file": "^1.0.0-beta.21",
152
+ "@nocobase/app-plugin-i18n": "^1.0.0-beta.13",
153
+ "@nocobase/app-plugin-notification": "^1.0.0-beta.24",
154
+ "@nocobase/app-plugin-notification-in-app": "^1.0.0-beta.22",
155
+ "@nocobase/app-plugin-notification-providers": "^0.2.0-beta.10",
156
+ "@nocobase/app-plugin-scheduler": "^1.0.0-beta.15",
157
+ "@nocobase/app-plugin-users": "^2.0.0-beta.1",
158
+ "@nocobase/app-plugin-workflow": "^2.0.0-beta.1",
159
+ "@nocobase/app-server": "^2.0.0-beta.2",
160
+ "@nocobase/config": "^0.1.0-beta.2",
161
+ "@nocobase/db": "^1.0.0-beta.18",
162
+ "@nocobase/db-sqlite": "^0.1.0-beta.4",
163
+ "@nocobase/service-provider": "^0.0.2-beta.1",
164
+ "@nocobase/snowflake": "^1.0.0-beta.3",
165
+ "@nocobase/app-plugin-authz-default-access": "^1.0.0-beta.10",
166
+ "@nocobase/app-plugin-authz-sharing-rules": "^1.0.0-beta.10",
167
+ "@nocobase/app-plugin-authz-restriction-rules": "^1.0.0-beta.9",
168
+ "@nocobase/authorization": "^1.0.0-beta.12",
169
+ "@nocobase/queue": "^0.1.0-beta.8",
170
+ "@nocobase/jobs": "^0.1.0-beta.2",
171
+ "@nocobase/i18n": "^1.0.0-beta.5",
172
+ "@nocobase/caching": "^0.1.0-beta.2",
173
+ "@nocobase/repository-input": "^0.1.0-beta.2",
174
+ "@nocobase/app-cli": "^1.0.0-beta.15"
175
+ },
176
+ "description": "NocoBase 3 application template with the standard product capabilities.",
177
+ "imports": {
178
+ "#components/*": "./client/components/*.js",
179
+ "#hooks/*": "./client/hooks/*.js",
180
+ "#lib/*": "./client/lib/*.js",
181
+ "#extensions/*": "./client/extensions/*.js",
182
+ "#pages/*": "./client/pages/*.js"
183
+ },
184
+ "scripts": {
185
+ "postinstall": "nocobase skills sync",
186
+ "dev": "nocobase dev",
187
+ "build": "nocobase build",
188
+ "start": "nocobase start",
189
+ "check": "pnpm lint && pnpm format:check && pnpm typecheck && pnpm test && pnpm build",
190
+ "fix": "pnpm lint:fix && pnpm format",
191
+ "typecheck": "tsc --noEmit && tsc -p tsconfig.node.json --noEmit && tsc -p tsconfig.server.json --noEmit",
192
+ "lint": "eslint . --max-warnings 0",
193
+ "lint:fix": "eslint . --fix --max-warnings 0",
194
+ "format": "prettier . --write",
195
+ "format:check": "prettier . --check",
196
+ "test": "vitest run",
197
+ "test:watch": "vitest",
198
+ "test:coverage": "vitest run --coverage",
199
+ "test:e2e": "playwright test --pass-with-no-tests"
200
+ }
6
201
  }
@@ -0,0 +1,10 @@
1
+ import { defineConfig } from '@playwright/test';
2
+
3
+ export default defineConfig({
4
+ testDir: './tests/playwright',
5
+ testMatch: '**/*.test.ts',
6
+ timeout: 120_000,
7
+ workers: 1,
8
+ reporter: 'list',
9
+ use: { trace: 'off' },
10
+ });
Binary file
Binary file
Binary file
Binary file
Binary file
package/server/app.ts ADDED
@@ -0,0 +1,50 @@
1
+ import type { Application } from '@nocobase/app-server/application';
2
+ import { DatabaseProvider } from '@nocobase/app-server/database';
3
+ import { I18nProvider, i18nHttpMiddleware } from '@nocobase/app-server/i18n';
4
+ import { CachingProvider } from '@nocobase/app-server/caching';
5
+ import { DriveProvider } from '@nocobase/app-server/drive';
6
+ import { IdGeneratorProvider } from '@nocobase/app-server/id-generator';
7
+ import {
8
+ LoggingProvider,
9
+ requestLoggingMiddleware,
10
+ } from '@nocobase/app-server/logging';
11
+ import { QueueServiceProvider } from '@nocobase/app-server/queue';
12
+ import { SecretsProvider } from '@nocobase/app-server/secrets';
13
+ import { JobExecutorServiceProvider } from '@nocobase/app-server/jobs';
14
+ import {
15
+ SessionProvider,
16
+ sessionHttpMiddleware,
17
+ } from '@nocobase/app-server/session';
18
+ import { healthCheckApiRoutes } from '@nocobase/app-server/router';
19
+ import {
20
+ createAppFromRuntime,
21
+ type AppRuntimeContext,
22
+ } from '@nocobase/app-server/runtime';
23
+ import { spaRootRoutes } from '@nocobase/app-server/spa';
24
+
25
+ export function createApp(runtime: AppRuntimeContext): Application {
26
+ const app = createAppFromRuntime(runtime);
27
+
28
+ app.addServiceProvider(DatabaseProvider);
29
+ app.addServiceProvider(I18nProvider);
30
+ app.addServiceProvider(LoggingProvider);
31
+ app.addServiceProvider(CachingProvider);
32
+ app.addServiceProvider(IdGeneratorProvider);
33
+ app.addServiceProvider(SecretsProvider);
34
+ app.addServiceProvider(SessionProvider);
35
+ app.addServiceProvider(DriveProvider);
36
+ app.addServiceProvider(QueueServiceProvider, {
37
+ nodeEnv: runtime.env.NODE_ENV,
38
+ });
39
+ app.addServiceProvider(JobExecutorServiceProvider, {
40
+ nodeEnv: runtime.env.NODE_ENV,
41
+ });
42
+ app.addHttpMiddleware(requestLoggingMiddleware);
43
+ app.addHttpMiddleware(sessionHttpMiddleware);
44
+ app.addHttpMiddleware(i18nHttpMiddleware);
45
+ app.addRoutes(healthCheckApiRoutes);
46
+ app.addRuntimeContributions(runtime);
47
+ app.addRoutes(spaRootRoutes);
48
+
49
+ return app;
50
+ }
@@ -0,0 +1,8 @@
1
+ import type { AppConfigFactory } from '@nocobase/app-server/config';
2
+ import { defineApiConfig, type ApiConfig } from '@nocobase/app-server/router';
3
+
4
+ // Limits every /api request meets ahead of its route: bodyLimit, timeout and rateLimit. Each is off until config.yml
5
+ // sets it; see the commented api section in config.example.yml. API_BODY_LIMIT and API_TIMEOUT set the first two.
6
+ const api: AppConfigFactory<ApiConfig> = defineApiConfig();
7
+
8
+ export default api;