@stone-js/starters 0.8.8 → 0.8.10
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.
- package/README.md +2 -2
- package/basic-react-declarative/app/Application.tsx +0 -2
- package/basic-react-declarative/package.json +7 -7
- package/basic-react-declarative/public/favicon.svg +16 -0
- package/basic-react-declarative/tests/Application.spec.ts +25 -100
- package/basic-react-imperative/app/Application.tsx +2 -17
- package/basic-react-imperative/package.json +7 -7
- package/basic-react-imperative/public/favicon.svg +16 -0
- package/basic-react-imperative/tests/Application.spec.ts +25 -86
- package/basic-react-native-declarative/App.tsx +192 -0
- package/basic-react-native-declarative/LICENSE +21 -0
- package/basic-react-native-declarative/README.md +35 -0
- package/basic-react-native-declarative/adapter/NativeAdapter.ts +108 -0
- package/basic-react-native-declarative/adapter/NativeErrorHandler.ts +53 -0
- package/basic-react-native-declarative/adapter/NativeEventSource.ts +58 -0
- package/basic-react-native-declarative/adapter/RawResponseWrapper.ts +30 -0
- package/basic-react-native-declarative/adapter/declarations.ts +40 -0
- package/basic-react-native-declarative/adapter/middleware.ts +73 -0
- package/basic-react-native-declarative/adapter/nativeAdapterBlueprint.ts +51 -0
- package/basic-react-native-declarative/adapter/renderSink.ts +52 -0
- package/basic-react-native-declarative/app/Application.ts +17 -0
- package/basic-react-native-declarative/app/WelcomeController.ts +66 -0
- package/basic-react-native-declarative/app.json +25 -0
- package/basic-react-native-declarative/assets/android-icon-background.png +0 -0
- package/basic-react-native-declarative/assets/android-icon-foreground.png +0 -0
- package/basic-react-native-declarative/assets/android-icon-monochrome.png +0 -0
- package/basic-react-native-declarative/assets/favicon.png +0 -0
- package/basic-react-native-declarative/assets/icon.png +0 -0
- package/basic-react-native-declarative/assets/splash-icon.png +0 -0
- package/basic-react-native-declarative/babel.config.js +16 -0
- package/basic-react-native-declarative/index.ts +22 -0
- package/basic-react-native-declarative/metro.config.js +7 -0
- package/basic-react-native-declarative/package.json +41 -0
- package/basic-react-native-declarative/tests/Application.spec.ts +65 -0
- package/basic-react-native-declarative/tsconfig.json +16 -0
- package/basic-react-native-declarative/vitest.config.ts +27 -0
- package/basic-service-declarative/app/Application.ts +0 -2
- package/basic-service-declarative/package.json +6 -6
- package/basic-service-declarative/tests/Application.spec.ts +20 -53
- package/basic-service-imperative/app/Application.ts +2 -14
- package/basic-service-imperative/package.json +6 -6
- package/basic-service-imperative/tests/Application.spec.ts +19 -44
- package/continuum-showcase/package.json +11 -10
- package/continuum-showcase/public/favicon.svg +16 -0
- package/continuum-showcase/stone.config.mjs +2 -2
- package/continuum-showcase/tests/application.spec.ts +30 -0
- package/full-react-declarative/app/Application.ts +0 -4
- package/full-react-declarative/package.json +12 -12
- package/full-react-declarative/public/favicon.svg +16 -0
- package/full-react-declarative/stone.config.mjs +2 -2
- package/full-react-declarative/tests/application.spec.ts +30 -0
- package/full-react-imperative/app/Application.ts +1 -3
- package/full-react-imperative/package.json +12 -12
- package/full-react-imperative/public/favicon.svg +16 -0
- package/full-react-imperative/stone.config.mjs +2 -2
- package/full-react-imperative/tests/application.spec.ts +30 -0
- package/full-service-declarative/app/Application.ts +5 -2
- package/full-service-declarative/app/configurations/AppConfiguration.ts +1 -3
- package/full-service-declarative/package.json +13 -12
- package/full-service-declarative/stone.config.mjs +2 -2
- package/full-service-declarative/tests/application.spec.ts +30 -0
- package/full-service-imperative/app/Application.ts +8 -2
- package/full-service-imperative/app/configurations/AppConfiguration.ts +1 -3
- package/full-service-imperative/package.json +13 -12
- package/full-service-imperative/stone.config.mjs +2 -2
- package/full-service-imperative/tests/application.spec.ts +30 -0
- package/package.json +15 -1
- package/standard-react-declarative/package.json +11 -10
- package/standard-react-declarative/public/favicon.svg +16 -0
- package/standard-react-declarative/tests/application.spec.ts +30 -0
- package/standard-react-imperative/package.json +11 -10
- package/standard-react-imperative/public/favicon.svg +16 -0
- package/standard-react-imperative/tests/application.spec.ts +30 -0
- package/standard-service-declarative/package.json +9 -8
- package/standard-service-declarative/tests/Application.spec.ts +22 -94
- package/standard-service-imperative/package.json +9 -8
- package/standard-service-imperative/tests/Application.spec.ts +22 -78
- package/basic-react-declarative/vitest.config.ts +0 -24
- package/basic-react-imperative/vitest.config.ts +0 -24
- package/basic-service-declarative/vitest.config.ts +0 -24
- package/basic-service-imperative/vitest.config.ts +0 -24
- package/continuum-showcase/tests/HomePage.spec.tsx +0 -41
- package/continuum-showcase/vitest.config.ts +0 -31
- package/full-react-declarative/tests/AppLayout.spec.ts +0 -51
- package/full-react-declarative/tests/HomePage.spec.ts +0 -38
- package/full-react-declarative/vitest.config.ts +0 -24
- package/full-react-imperative/tests/HomePage.spec.ts +0 -45
- package/full-react-imperative/tests/LayoutHeader.spec.ts +0 -39
- package/full-react-imperative/vitest.config.ts +0 -24
- package/full-service-declarative/tests/PostService.spec.ts +0 -56
- package/full-service-declarative/tests/WelcomeEventHandler.spec.ts +0 -54
- package/full-service-declarative/vitest.config.ts +0 -24
- package/full-service-imperative/tests/PostService.spec.ts +0 -47
- package/full-service-imperative/tests/WelcomeEventHandler.spec.ts +0 -31
- package/full-service-imperative/vitest.config.ts +0 -24
- package/standard-react-declarative/tests/WelcomePage.spec.ts +0 -71
- package/standard-react-declarative/vitest.config.ts +0 -24
- package/standard-react-imperative/tests/WelcomePage.spec.ts +0 -53
- package/standard-react-imperative/vitest.config.ts +0 -24
- package/standard-service-declarative/vitest.config.ts +0 -24
- package/standard-service-imperative/vitest.config.ts +0 -24
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { routerBlueprint } from '@stone-js/router'
|
|
2
2
|
import { browserAdapterBlueprint } from '@stone-js/browser-adapter'
|
|
3
3
|
import { nodeHttpAdapterBlueprint } from '@stone-js/node-http-adapter'
|
|
4
|
-
import { nodeConsoleAdapterBlueprint } from '@stone-js/node-cli-adapter'
|
|
5
4
|
import { defineStoneReactApp, ReactLifecycleHookType } from '@stone-js/use-react'
|
|
6
5
|
import { defineHookListeners, IBlueprint, IContainer, ILogger, LogLevel, Promiseable } from '@stone-js/core'
|
|
7
6
|
|
|
@@ -61,8 +60,7 @@ export const MyStoneReactApp = defineStoneReactApp(
|
|
|
61
60
|
[
|
|
62
61
|
routerBlueprint,
|
|
63
62
|
browserAdapterBlueprint,
|
|
64
|
-
nodeHttpAdapterBlueprint
|
|
65
|
-
nodeConsoleAdapterBlueprint
|
|
63
|
+
nodeHttpAdapterBlueprint
|
|
66
64
|
]
|
|
67
65
|
)
|
|
68
66
|
|
|
@@ -14,19 +14,18 @@
|
|
|
14
14
|
"build": "stone build",
|
|
15
15
|
"preview": "stone preview",
|
|
16
16
|
"build:ssr": "stone build --ssr",
|
|
17
|
-
"test": "
|
|
18
|
-
"test:cvg": "
|
|
17
|
+
"test": "stone test",
|
|
18
|
+
"test:cvg": "stone test --coverage"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@stone-js/env": "^0.8.
|
|
22
|
-
"@stone-js/http-core": "^0.8.
|
|
23
|
-
"@stone-js/node-http-adapter": "^0.8.
|
|
24
|
-
"@stone-js/router": "^0.8.
|
|
25
|
-
"@stone-js/filesystem": "^0.8.
|
|
26
|
-
"@stone-js/core": "^0.8.
|
|
27
|
-
"@stone-js/use-react": "^0.8.
|
|
28
|
-
"@stone-js/browser-adapter": "^0.8.
|
|
29
|
-
"@stone-js/node-cli-adapter": "^0.8.8",
|
|
21
|
+
"@stone-js/env": "^0.8.10",
|
|
22
|
+
"@stone-js/http-core": "^0.8.10",
|
|
23
|
+
"@stone-js/node-http-adapter": "^0.8.10",
|
|
24
|
+
"@stone-js/router": "^0.8.10",
|
|
25
|
+
"@stone-js/filesystem": "^0.8.10",
|
|
26
|
+
"@stone-js/core": "^0.8.10",
|
|
27
|
+
"@stone-js/use-react": "^0.8.10",
|
|
28
|
+
"@stone-js/browser-adapter": "^0.8.10",
|
|
30
29
|
"axios": "^1.7.9",
|
|
31
30
|
"dayjs": "^1.11.13",
|
|
32
31
|
"react": "^19.0.0",
|
|
@@ -36,7 +35,8 @@
|
|
|
36
35
|
"@babel/plugin-proposal-decorators": "^7.25.9",
|
|
37
36
|
"@babel/preset-env": "^7.26.9",
|
|
38
37
|
"@babel/preset-typescript": "^7.27.0",
|
|
39
|
-
"@stone-js/cli": "^0.8.
|
|
38
|
+
"@stone-js/cli": "^0.8.10",
|
|
39
|
+
"@stone-js/testing": "^0.8.10",
|
|
40
40
|
"@types/axios": "^0.14.4",
|
|
41
41
|
"@types/node": "^24.0.7",
|
|
42
42
|
"@types/react": "^19.0.7",
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96" width="96" height="96" role="img" aria-label="Stone.js">
|
|
2
|
+
<title>Stone.js</title>
|
|
3
|
+
<style>
|
|
4
|
+
.ink { stroke: #1B1613; }
|
|
5
|
+
@media (prefers-color-scheme: dark) { .ink { stroke: #EFE8DC; } }
|
|
6
|
+
</style>
|
|
7
|
+
<defs>
|
|
8
|
+
<linearGradient id="braise" gradientUnits="userSpaceOnUse" x1="22" y1="14" x2="74" y2="26.1">
|
|
9
|
+
<stop offset="0" stop-color="#FFC46B" />
|
|
10
|
+
<stop offset="1" stop-color="#FF5A1F" />
|
|
11
|
+
</linearGradient>
|
|
12
|
+
</defs>
|
|
13
|
+
<path class="ink" d="M 79.96 36.4 A 34 34 0 0 1 53.9 81.5" fill="none" stroke-width="11" stroke-linecap="round" opacity=".85" />
|
|
14
|
+
<path class="ink" d="M 42.1 81.5 A 34 34 0 0 1 16.05 36.4" fill="none" stroke-width="11" stroke-linecap="round" opacity=".85" />
|
|
15
|
+
<path d="M 22 26.1 A 34 34 0 0 1 74 26.1" fill="none" stroke="url(#braise)" stroke-width="11" stroke-linecap="round" />
|
|
16
|
+
</svg>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineBuilderConfig } from '@stone-js/cli'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Stone build configuration.
|
|
5
5
|
*/
|
|
6
|
-
export default
|
|
6
|
+
export default defineBuilderConfig({
|
|
7
7
|
dotenv: {
|
|
8
8
|
private: {
|
|
9
9
|
path: ['.env', '.env.public'],
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createTestApp, makeIncomingHttpEvent } from '@stone-js/testing'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The whole application, booted in memory and asked a real question.
|
|
5
|
+
*
|
|
6
|
+
* Nothing is mocked and nothing is listed: `createTestApp()` discovers `app/**`, and the event goes
|
|
7
|
+
* through the same kernel production runs. If this passes the application works; if it fails the
|
|
8
|
+
* application is broken. That is the only kind of test worth shipping in a starter — the previous one
|
|
9
|
+
* stubbed out the framework's own decorators, which meant it could pass while nothing worked.
|
|
10
|
+
*/
|
|
11
|
+
describe('Pages', () => {
|
|
12
|
+
it('renders the home page, data included', async () => {
|
|
13
|
+
const app = await createTestApp()
|
|
14
|
+
|
|
15
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/?name=Ada' }))
|
|
16
|
+
|
|
17
|
+
expect(response.statusCode).toBe(200)
|
|
18
|
+
// A page is a handler, so a rendered page is a response whose body is HTML. Query that HTML with
|
|
19
|
+
// whatever you already use (happy-dom, jsdom, Testing Library): none is bundled here.
|
|
20
|
+
expect(response.html()).toContain('Ada')
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('renders without a name', async () => {
|
|
24
|
+
const app = await createTestApp()
|
|
25
|
+
|
|
26
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/' }))
|
|
27
|
+
|
|
28
|
+
expect(response.statusCode).toBe(200)
|
|
29
|
+
})
|
|
30
|
+
})
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Cors,
|
|
2
3
|
IncomingHttpEvent,
|
|
3
4
|
OutgoingHttpResponse,
|
|
4
5
|
IncomingHttpEventOptions
|
|
5
6
|
} from '@stone-js/http-core'
|
|
6
7
|
import {
|
|
7
8
|
NodeHttp,
|
|
8
|
-
MetaBodyEventMiddleware,
|
|
9
9
|
MetaFilesEventMiddleware
|
|
10
10
|
} from '@stone-js/node-http-adapter'
|
|
11
11
|
import {
|
|
@@ -35,15 +35,18 @@ import { PipelineHookContext } from '@stone-js/pipeline'
|
|
|
35
35
|
* @NodeHttp() is used to enable the Node HTTP adapter.
|
|
36
36
|
* @NodeConsole() is used to enable the Node Console adapter.
|
|
37
37
|
* @NodeConsole() requires the incoming event type.
|
|
38
|
+
* @Cors() answers cross-origin requests, on the kernel and the adapter alike.
|
|
39
|
+
* Nothing is allowed until you name the origins you trust: add `origin: ['https://your-front']`.
|
|
38
40
|
* BodyEventMiddleware is used to parse the incoming event body.
|
|
39
41
|
* BodyEventMiddleware is imported because it is not installed by default.
|
|
40
42
|
*
|
|
41
43
|
* Note: In this example we implement the IBlueprintHook, IAdapterHook and IKernelHook interfaces for demonstration purposes.
|
|
42
44
|
*/
|
|
45
|
+
@Cors({ preflightStop: true, allowedHeaders: ['*'] })
|
|
43
46
|
@Routing()
|
|
44
47
|
@NodeConsole()
|
|
45
48
|
@StoneApp({ name: 'MyApps', logger: { level: LogLevel.INFO } })
|
|
46
|
-
@NodeHttp({ default: true, middleware: [
|
|
49
|
+
@NodeHttp({ default: true, middleware: [MetaFilesEventMiddleware], url: getString('BASE_URL', 'http://localhost:8080') })
|
|
47
50
|
export class Application {
|
|
48
51
|
/**
|
|
49
52
|
* Run before the blueprint is prepared
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Config } from '@libsql/client'
|
|
2
2
|
import { getString } from '@stone-js/env'
|
|
3
|
-
import {
|
|
4
|
-
import { Configuration, defineBlueprintMiddleware, IBlueprint, IConfiguration, LogLevel, Promiseable } from '@stone-js/core'
|
|
3
|
+
import { Configuration, IBlueprint, IConfiguration, LogLevel, Promiseable } from '@stone-js/core'
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* User Implicit Configuration
|
|
@@ -23,7 +22,6 @@ export class AppConfiguration implements IConfiguration {
|
|
|
23
22
|
.set('stone.logger.level', LogLevel.INFO)
|
|
24
23
|
.set('stone.http.cors.preflightStop', true)
|
|
25
24
|
.set('stone.http.cors.allowedHeaders', ['*'])
|
|
26
|
-
.set(defineBlueprintMiddleware(CORSHeadersMiddleware))
|
|
27
25
|
}
|
|
28
26
|
|
|
29
27
|
/**
|
|
@@ -17,28 +17,29 @@
|
|
|
17
17
|
"db:setup": "drizzle-kit push",
|
|
18
18
|
"db:generate": "drizzle-kit generate",
|
|
19
19
|
"db:migrate": "drizzle-kit migrate",
|
|
20
|
-
"test": "
|
|
21
|
-
"test:cvg": "
|
|
20
|
+
"test": "stone test",
|
|
21
|
+
"test:cvg": "stone test --coverage"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@libsql/client": "^0.14.0",
|
|
25
|
-
"@stone-js/core": "^0.8.
|
|
26
|
-
"@stone-js/env": "^0.8.
|
|
27
|
-
"@stone-js/filesystem": "^0.8.
|
|
28
|
-
"@stone-js/http-core": "^0.8.
|
|
29
|
-
"@stone-js/node-cli-adapter": "^0.8.
|
|
30
|
-
"@stone-js/node-http-adapter": "^0.8.
|
|
31
|
-
"@stone-js/pipeline": "^0.8.
|
|
32
|
-
"@stone-js/router": "^0.8.
|
|
25
|
+
"@stone-js/core": "^0.8.10",
|
|
26
|
+
"@stone-js/env": "^0.8.10",
|
|
27
|
+
"@stone-js/filesystem": "^0.8.10",
|
|
28
|
+
"@stone-js/http-core": "^0.8.10",
|
|
29
|
+
"@stone-js/node-cli-adapter": "^0.8.10",
|
|
30
|
+
"@stone-js/node-http-adapter": "^0.8.10",
|
|
31
|
+
"@stone-js/pipeline": "^0.8.10",
|
|
32
|
+
"@stone-js/router": "^0.8.10",
|
|
33
33
|
"bcryptjs": "^3.0.2",
|
|
34
|
-
"drizzle-orm": "^0.
|
|
34
|
+
"drizzle-orm": "^0.45.2",
|
|
35
35
|
"jsonwebtoken": "^9.0.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@babel/plugin-proposal-decorators": "^7.25.9",
|
|
39
39
|
"@babel/preset-env": "^7.26.9",
|
|
40
40
|
"@babel/preset-typescript": "^7.27.0",
|
|
41
|
-
"@stone-js/cli": "^0.8.
|
|
41
|
+
"@stone-js/cli": "^0.8.10",
|
|
42
|
+
"@stone-js/testing": "^0.8.10",
|
|
42
43
|
"@types/jsonwebtoken": "^9.0.8",
|
|
43
44
|
"@types/node": "^24.0.3",
|
|
44
45
|
"@vitest/coverage-v8": "^3.0.9",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineBuilderConfig } from '@stone-js/cli'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Stone build configuration.
|
|
5
5
|
*/
|
|
6
|
-
export default
|
|
6
|
+
export default defineBuilderConfig({
|
|
7
7
|
rollup: {
|
|
8
8
|
bundle: {
|
|
9
9
|
external: ['@libsql/client'],
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createTestApp, makeIncomingHttpEvent } from '@stone-js/testing'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The whole application, booted in memory and asked a real question.
|
|
5
|
+
*
|
|
6
|
+
* Nothing is mocked and nothing is listed: `createTestApp()` discovers `app/**`, and the event goes
|
|
7
|
+
* through the same kernel production runs. If this passes the application works; if it fails the
|
|
8
|
+
* application is broken. That is the only kind of test worth shipping in a starter — the previous one
|
|
9
|
+
* stubbed out the framework's own decorators, which meant it could pass while nothing worked.
|
|
10
|
+
*/
|
|
11
|
+
describe('Application', () => {
|
|
12
|
+
it('answers on the public welcome route', async () => {
|
|
13
|
+
const app = await createTestApp()
|
|
14
|
+
|
|
15
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/' }))
|
|
16
|
+
|
|
17
|
+
expect(response.statusCode).toBe(200)
|
|
18
|
+
expect(response.json()).toMatchObject({ message: expect.stringContaining('Stone.js') })
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('refuses an unauthenticated request to a protected route', async () => {
|
|
22
|
+
// Substitute a repository with `bindings` when a route needs data:
|
|
23
|
+
// createTestApp({ bindings: { userRepository: fakeRepository } })
|
|
24
|
+
const app = await createTestApp()
|
|
25
|
+
|
|
26
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/users' }))
|
|
27
|
+
|
|
28
|
+
expect(response.statusCode).toBeGreaterThanOrEqual(400)
|
|
29
|
+
})
|
|
30
|
+
})
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
corsBlueprint,
|
|
2
3
|
IncomingHttpEvent,
|
|
3
4
|
OutgoingHttpResponse,
|
|
4
5
|
IncomingHttpEventOptions
|
|
@@ -21,7 +22,7 @@ import { getString } from '@stone-js/env'
|
|
|
21
22
|
import { routerBlueprint } from '@stone-js/router'
|
|
22
23
|
import { PipelineHookContext } from '@stone-js/pipeline'
|
|
23
24
|
import { nodeConsoleAdapterBlueprint } from '@stone-js/node-cli-adapter'
|
|
24
|
-
import {
|
|
25
|
+
import { MetaFilesEventMiddleware, NODE_HTTP_PLATFORM, nodeHttpAdapterBlueprint } from '@stone-js/node-http-adapter'
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
28
|
* Run before the blueprint is prepared
|
|
@@ -288,6 +289,7 @@ export const onTerminate = defineHookListener((container: IContainer): void => {
|
|
|
288
289
|
export const Application = defineStoneApp(
|
|
289
290
|
{ name: 'MyApp', logger: { level: LogLevel.INFO } },
|
|
290
291
|
[
|
|
292
|
+
corsBlueprint,
|
|
291
293
|
routerBlueprint,
|
|
292
294
|
nodeHttpAdapterBlueprint,
|
|
293
295
|
nodeConsoleAdapterBlueprint
|
|
@@ -308,10 +310,14 @@ export const AppConfig = defineConfig({
|
|
|
308
310
|
})
|
|
309
311
|
},
|
|
310
312
|
afterConfigure (blueprint: IBlueprint) {
|
|
313
|
+
// Nothing is allowed cross-origin until you name the origins you trust:
|
|
314
|
+
// add `origin: ['https://your-front']` here.
|
|
315
|
+
blueprint.set('stone.http.cors', { preflightStop: true, allowedHeaders: ['*'] })
|
|
316
|
+
|
|
311
317
|
if (blueprint.is('stone.adapter.platform', NODE_HTTP_PLATFORM)) {
|
|
312
318
|
blueprint
|
|
313
319
|
.set('stone.adapter.url', getString('BASE_URL', 'http://localhost:8080'))
|
|
314
|
-
.add('stone.adapter.middleware', [
|
|
320
|
+
.add('stone.adapter.middleware', [MetaFilesEventMiddleware])
|
|
315
321
|
}
|
|
316
322
|
}
|
|
317
323
|
})
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Config } from '@libsql/client'
|
|
2
2
|
import { getString } from '@stone-js/env'
|
|
3
|
-
import {
|
|
4
|
-
import { defineBlueprintMiddleware, defineConfig, IBlueprint, LogLevel, Promiseable } from '@stone-js/core'
|
|
3
|
+
import { defineConfig, IBlueprint, LogLevel, Promiseable } from '@stone-js/core'
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* User Implicit Configuration
|
|
@@ -16,7 +15,6 @@ export const AppConfiguration = defineConfig((blueprint: IBlueprint): Promiseabl
|
|
|
16
15
|
.set('stone.logger.level', LogLevel.INFO)
|
|
17
16
|
.set('stone.http.cors.preflightStop', true)
|
|
18
17
|
.set('stone.http.cors.allowedHeaders', ['*'])
|
|
19
|
-
.set(defineBlueprintMiddleware(CORSHeadersMiddleware))
|
|
20
18
|
})
|
|
21
19
|
|
|
22
20
|
/**
|
|
@@ -17,28 +17,29 @@
|
|
|
17
17
|
"db:setup": "drizzle-kit push",
|
|
18
18
|
"db:generate": "drizzle-kit generate",
|
|
19
19
|
"db:migrate": "drizzle-kit migrate",
|
|
20
|
-
"test": "
|
|
21
|
-
"test:cvg": "
|
|
20
|
+
"test": "stone test",
|
|
21
|
+
"test:cvg": "stone test --coverage"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@libsql/client": "^0.14.0",
|
|
25
|
-
"@stone-js/core": "^0.8.
|
|
26
|
-
"@stone-js/env": "^0.8.
|
|
27
|
-
"@stone-js/filesystem": "^0.8.
|
|
28
|
-
"@stone-js/http-core": "^0.8.
|
|
29
|
-
"@stone-js/node-cli-adapter": "^0.8.
|
|
30
|
-
"@stone-js/node-http-adapter": "^0.8.
|
|
31
|
-
"@stone-js/pipeline": "^0.8.
|
|
32
|
-
"@stone-js/router": "^0.8.
|
|
25
|
+
"@stone-js/core": "^0.8.10",
|
|
26
|
+
"@stone-js/env": "^0.8.10",
|
|
27
|
+
"@stone-js/filesystem": "^0.8.10",
|
|
28
|
+
"@stone-js/http-core": "^0.8.10",
|
|
29
|
+
"@stone-js/node-cli-adapter": "^0.8.10",
|
|
30
|
+
"@stone-js/node-http-adapter": "^0.8.10",
|
|
31
|
+
"@stone-js/pipeline": "^0.8.10",
|
|
32
|
+
"@stone-js/router": "^0.8.10",
|
|
33
33
|
"bcryptjs": "^3.0.2",
|
|
34
|
-
"drizzle-orm": "^0.
|
|
34
|
+
"drizzle-orm": "^0.45.2",
|
|
35
35
|
"jsonwebtoken": "^9.0.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@babel/plugin-proposal-decorators": "^7.25.9",
|
|
39
39
|
"@babel/preset-env": "^7.26.9",
|
|
40
40
|
"@babel/preset-typescript": "^7.27.0",
|
|
41
|
-
"@stone-js/cli": "^0.8.
|
|
41
|
+
"@stone-js/cli": "^0.8.10",
|
|
42
|
+
"@stone-js/testing": "^0.8.10",
|
|
42
43
|
"@types/jsonwebtoken": "^9.0.8",
|
|
43
44
|
"@types/node": "^24.0.3",
|
|
44
45
|
"@vitest/coverage-v8": "^3.0.9",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineBuilderConfig } from '@stone-js/cli'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Stone build configuration.
|
|
5
5
|
*/
|
|
6
|
-
export default
|
|
6
|
+
export default defineBuilderConfig({
|
|
7
7
|
rollup: {
|
|
8
8
|
bundle: {
|
|
9
9
|
external: ['@libsql/client'],
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createTestApp, makeIncomingHttpEvent } from '@stone-js/testing'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The whole application, booted in memory and asked a real question.
|
|
5
|
+
*
|
|
6
|
+
* Nothing is mocked and nothing is listed: `createTestApp()` discovers `app/**`, and the event goes
|
|
7
|
+
* through the same kernel production runs. If this passes the application works; if it fails the
|
|
8
|
+
* application is broken. That is the only kind of test worth shipping in a starter — the previous one
|
|
9
|
+
* stubbed out the framework's own decorators, which meant it could pass while nothing worked.
|
|
10
|
+
*/
|
|
11
|
+
describe('Application', () => {
|
|
12
|
+
it('answers on the public welcome route', async () => {
|
|
13
|
+
const app = await createTestApp()
|
|
14
|
+
|
|
15
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/' }))
|
|
16
|
+
|
|
17
|
+
expect(response.statusCode).toBe(200)
|
|
18
|
+
expect(response.json()).toMatchObject({ message: expect.stringContaining('Stone.js') })
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('refuses an unauthenticated request to a protected route', async () => {
|
|
22
|
+
// Substitute a repository with `bindings` when a route needs data:
|
|
23
|
+
// createTestApp({ bindings: { userRepository: fakeRepository } })
|
|
24
|
+
const app = await createTestApp()
|
|
25
|
+
|
|
26
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/users' }))
|
|
27
|
+
|
|
28
|
+
expect(response.statusCode).toBeGreaterThanOrEqual(400)
|
|
29
|
+
})
|
|
30
|
+
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stone-js/starters",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.10",
|
|
4
4
|
"description": "This repository contains official **starter templates** for Stone.js applications.",
|
|
5
5
|
"author": "Mr. Stone <evensstone@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -170,6 +170,19 @@
|
|
|
170
170
|
],
|
|
171
171
|
"path": "full-react-imperative"
|
|
172
172
|
},
|
|
173
|
+
{
|
|
174
|
+
"value": "basic-react-native-declarative",
|
|
175
|
+
"title": "Basic · React Native · declarative (Expo)",
|
|
176
|
+
"description": "Native mobile app with React Native and Expo, decorator API.",
|
|
177
|
+
"tags": [
|
|
178
|
+
"react-native",
|
|
179
|
+
"expo",
|
|
180
|
+
"mobile",
|
|
181
|
+
"basic",
|
|
182
|
+
"declarative"
|
|
183
|
+
],
|
|
184
|
+
"path": "basic-react-native-declarative"
|
|
185
|
+
},
|
|
173
186
|
{
|
|
174
187
|
"value": "continuum-showcase",
|
|
175
188
|
"title": "Continuum showcase",
|
|
@@ -212,6 +225,7 @@
|
|
|
212
225
|
"full-service-imperative",
|
|
213
226
|
"full-react-declarative",
|
|
214
227
|
"full-react-imperative",
|
|
228
|
+
"basic-react-native-declarative",
|
|
215
229
|
"continuum-showcase"
|
|
216
230
|
],
|
|
217
231
|
"publishConfig": {
|
|
@@ -14,25 +14,26 @@
|
|
|
14
14
|
"build": "stone build",
|
|
15
15
|
"preview": "stone preview",
|
|
16
16
|
"typings": "stone typings",
|
|
17
|
-
"test": "
|
|
18
|
-
"test:cvg": "
|
|
17
|
+
"test": "stone test",
|
|
18
|
+
"test:cvg": "stone test --coverage"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"react": "^19.0.0",
|
|
22
22
|
"react-dom": "^19.0.0",
|
|
23
|
-
"@stone-js/use-react": "^0.8.
|
|
24
|
-
"@stone-js/browser-adapter": "^0.8.
|
|
25
|
-
"@stone-js/pipeline": "^0.8.
|
|
26
|
-
"@stone-js/http-core": "^0.8.
|
|
27
|
-
"@stone-js/node-http-adapter": "^0.8.
|
|
28
|
-
"@stone-js/router": "^0.8.
|
|
29
|
-
"@stone-js/core": "^0.8.
|
|
23
|
+
"@stone-js/use-react": "^0.8.10",
|
|
24
|
+
"@stone-js/browser-adapter": "^0.8.10",
|
|
25
|
+
"@stone-js/pipeline": "^0.8.10",
|
|
26
|
+
"@stone-js/http-core": "^0.8.10",
|
|
27
|
+
"@stone-js/node-http-adapter": "^0.8.10",
|
|
28
|
+
"@stone-js/router": "^0.8.10",
|
|
29
|
+
"@stone-js/core": "^0.8.10"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@babel/plugin-proposal-decorators": "^7.25.9",
|
|
33
33
|
"@babel/preset-env": "^7.26.9",
|
|
34
34
|
"@babel/preset-typescript": "^7.27.0",
|
|
35
|
-
"@stone-js/cli": "^0.8.
|
|
35
|
+
"@stone-js/cli": "^0.8.10",
|
|
36
|
+
"@stone-js/testing": "^0.8.10",
|
|
36
37
|
"@types/node": "^24.0.7",
|
|
37
38
|
"@types/react": "^19.0.7",
|
|
38
39
|
"@types/react-dom": "^19.0.3",
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96" width="96" height="96" role="img" aria-label="Stone.js">
|
|
2
|
+
<title>Stone.js</title>
|
|
3
|
+
<style>
|
|
4
|
+
.ink { stroke: #1B1613; }
|
|
5
|
+
@media (prefers-color-scheme: dark) { .ink { stroke: #EFE8DC; } }
|
|
6
|
+
</style>
|
|
7
|
+
<defs>
|
|
8
|
+
<linearGradient id="braise" gradientUnits="userSpaceOnUse" x1="22" y1="14" x2="74" y2="26.1">
|
|
9
|
+
<stop offset="0" stop-color="#FFC46B" />
|
|
10
|
+
<stop offset="1" stop-color="#FF5A1F" />
|
|
11
|
+
</linearGradient>
|
|
12
|
+
</defs>
|
|
13
|
+
<path class="ink" d="M 79.96 36.4 A 34 34 0 0 1 53.9 81.5" fill="none" stroke-width="11" stroke-linecap="round" opacity=".85" />
|
|
14
|
+
<path class="ink" d="M 42.1 81.5 A 34 34 0 0 1 16.05 36.4" fill="none" stroke-width="11" stroke-linecap="round" opacity=".85" />
|
|
15
|
+
<path d="M 22 26.1 A 34 34 0 0 1 74 26.1" fill="none" stroke="url(#braise)" stroke-width="11" stroke-linecap="round" />
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createTestApp, makeIncomingHttpEvent } from '@stone-js/testing'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The whole application, booted in memory and asked a real question.
|
|
5
|
+
*
|
|
6
|
+
* Nothing is mocked and nothing is listed: `createTestApp()` discovers `app/**`, and the event goes
|
|
7
|
+
* through the same kernel production runs. If this passes the application works; if it fails the
|
|
8
|
+
* application is broken. That is the only kind of test worth shipping in a starter — the previous one
|
|
9
|
+
* stubbed out the framework's own decorators, which meant it could pass while nothing worked.
|
|
10
|
+
*/
|
|
11
|
+
describe('Pages', () => {
|
|
12
|
+
it('renders the home page, data included', async () => {
|
|
13
|
+
const app = await createTestApp()
|
|
14
|
+
|
|
15
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/?name=Ada' }))
|
|
16
|
+
|
|
17
|
+
expect(response.statusCode).toBe(200)
|
|
18
|
+
// A page is a handler, so a rendered page is a response whose body is HTML. Query that HTML with
|
|
19
|
+
// whatever you already use (happy-dom, jsdom, Testing Library): none is bundled here.
|
|
20
|
+
expect(response.html()).toContain('Ada')
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('renders without a name', async () => {
|
|
24
|
+
const app = await createTestApp()
|
|
25
|
+
|
|
26
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/' }))
|
|
27
|
+
|
|
28
|
+
expect(response.statusCode).toBe(200)
|
|
29
|
+
})
|
|
30
|
+
})
|
|
@@ -14,25 +14,26 @@
|
|
|
14
14
|
"build": "stone build",
|
|
15
15
|
"preview": "stone preview",
|
|
16
16
|
"typings": "stone typings",
|
|
17
|
-
"test": "
|
|
18
|
-
"test:cvg": "
|
|
17
|
+
"test": "stone test",
|
|
18
|
+
"test:cvg": "stone test --coverage"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"react": "^19.0.0",
|
|
22
22
|
"react-dom": "^19.0.0",
|
|
23
|
-
"@stone-js/use-react": "^0.8.
|
|
24
|
-
"@stone-js/browser-adapter": "^0.8.
|
|
25
|
-
"@stone-js/pipeline": "^0.8.
|
|
26
|
-
"@stone-js/http-core": "^0.8.
|
|
27
|
-
"@stone-js/node-http-adapter": "^0.8.
|
|
28
|
-
"@stone-js/router": "^0.8.
|
|
29
|
-
"@stone-js/core": "^0.8.
|
|
23
|
+
"@stone-js/use-react": "^0.8.10",
|
|
24
|
+
"@stone-js/browser-adapter": "^0.8.10",
|
|
25
|
+
"@stone-js/pipeline": "^0.8.10",
|
|
26
|
+
"@stone-js/http-core": "^0.8.10",
|
|
27
|
+
"@stone-js/node-http-adapter": "^0.8.10",
|
|
28
|
+
"@stone-js/router": "^0.8.10",
|
|
29
|
+
"@stone-js/core": "^0.8.10"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@babel/plugin-proposal-decorators": "^7.25.9",
|
|
33
33
|
"@babel/preset-env": "^7.26.9",
|
|
34
34
|
"@babel/preset-typescript": "^7.27.0",
|
|
35
|
-
"@stone-js/cli": "^0.8.
|
|
35
|
+
"@stone-js/cli": "^0.8.10",
|
|
36
|
+
"@stone-js/testing": "^0.8.10",
|
|
36
37
|
"@types/node": "^24.0.7",
|
|
37
38
|
"@types/react": "^19.0.7",
|
|
38
39
|
"@types/react-dom": "^19.0.3",
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96" width="96" height="96" role="img" aria-label="Stone.js">
|
|
2
|
+
<title>Stone.js</title>
|
|
3
|
+
<style>
|
|
4
|
+
.ink { stroke: #1B1613; }
|
|
5
|
+
@media (prefers-color-scheme: dark) { .ink { stroke: #EFE8DC; } }
|
|
6
|
+
</style>
|
|
7
|
+
<defs>
|
|
8
|
+
<linearGradient id="braise" gradientUnits="userSpaceOnUse" x1="22" y1="14" x2="74" y2="26.1">
|
|
9
|
+
<stop offset="0" stop-color="#FFC46B" />
|
|
10
|
+
<stop offset="1" stop-color="#FF5A1F" />
|
|
11
|
+
</linearGradient>
|
|
12
|
+
</defs>
|
|
13
|
+
<path class="ink" d="M 79.96 36.4 A 34 34 0 0 1 53.9 81.5" fill="none" stroke-width="11" stroke-linecap="round" opacity=".85" />
|
|
14
|
+
<path class="ink" d="M 42.1 81.5 A 34 34 0 0 1 16.05 36.4" fill="none" stroke-width="11" stroke-linecap="round" opacity=".85" />
|
|
15
|
+
<path d="M 22 26.1 A 34 34 0 0 1 74 26.1" fill="none" stroke="url(#braise)" stroke-width="11" stroke-linecap="round" />
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createTestApp, makeIncomingHttpEvent } from '@stone-js/testing'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The whole application, booted in memory and asked a real question.
|
|
5
|
+
*
|
|
6
|
+
* Nothing is mocked and nothing is listed: `createTestApp()` discovers `app/**`, and the event goes
|
|
7
|
+
* through the same kernel production runs. If this passes the application works; if it fails the
|
|
8
|
+
* application is broken. That is the only kind of test worth shipping in a starter — the previous one
|
|
9
|
+
* stubbed out the framework's own decorators, which meant it could pass while nothing worked.
|
|
10
|
+
*/
|
|
11
|
+
describe('Pages', () => {
|
|
12
|
+
it('renders the home page, data included', async () => {
|
|
13
|
+
const app = await createTestApp()
|
|
14
|
+
|
|
15
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/?name=Ada' }))
|
|
16
|
+
|
|
17
|
+
expect(response.statusCode).toBe(200)
|
|
18
|
+
// A page is a handler, so a rendered page is a response whose body is HTML. Query that HTML with
|
|
19
|
+
// whatever you already use (happy-dom, jsdom, Testing Library): none is bundled here.
|
|
20
|
+
expect(response.html()).toContain('Ada')
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('renders without a name', async () => {
|
|
24
|
+
const app = await createTestApp()
|
|
25
|
+
|
|
26
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/' }))
|
|
27
|
+
|
|
28
|
+
expect(response.statusCode).toBe(200)
|
|
29
|
+
})
|
|
30
|
+
})
|