create-octane-xplat 0.3.0 → 0.4.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.
- package/README.md +25 -0
- package/index.mjs +20 -17
- package/package.json +2 -2
- package/template/.oxlintrc.json +25 -0
- package/template/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json +121 -121
- package/template/App_Resources/iOS/Assets.xcassets/Contents.json +5 -5
- package/template/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json +22 -22
- package/template/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json +22 -22
- package/template/App_Resources/iOS/Assets.xcassets/octane.imageset/Contents.json +6 -6
- package/template/index.html +9 -9
- package/template/nativescript.config.ts +11 -11
- package/template/package.json +40 -35
- package/template/src/{native.ts → index.native.ts} +14 -14
- package/template/src/style.css +2 -0
- package/template/tsconfig.json +1 -1
- package/template/vite.config.native.mts +7 -84
- package/template/vite.config.ts +14 -7
package/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# create-octane-xplat
|
|
2
|
+
|
|
3
|
+
> Scaffolds an Octane xplat app — one codebase targeting web, iOS, and
|
|
4
|
+
> Android via NativeScript.
|
|
5
|
+
>
|
|
6
|
+
> Status: `0.x` — the API surface is still moving. iOS/Android targets need
|
|
7
|
+
> the NativeScript toolchain (Xcode/JDK + `ns`).
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
pnpm create octane-xplat my-app
|
|
11
|
+
# or: npm create octane-xplat my-app
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Copies the starter template (vite + nativescript configs, shared `src/`,
|
|
15
|
+
`App_Resources`, pinned workspace deps), installs dependencies with pnpm,
|
|
16
|
+
and starts the web dev server. From there:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
pnpm dev # web
|
|
20
|
+
pnpm dev:ios # iOS simulator — needs the NativeScript toolchain
|
|
21
|
+
pnpm dev:android # Android — needs the NativeScript toolchain
|
|
22
|
+
pnpm typecheck # web + native tsconfigs
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Docs: [Running and checking an app](https://octane-xplat.goddardai.org/toolchain)
|
package/index.mjs
CHANGED
|
@@ -1,28 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { existsSync, readdirSync, cpSync, renameSync } from 'node:fs'
|
|
3
|
-
import { dirname, join, resolve } from 'node:path'
|
|
4
|
-
import { fileURLToPath } from 'node:url'
|
|
5
|
-
import { spawnSync } from 'node:child_process'
|
|
2
|
+
import { existsSync, readdirSync, cpSync, renameSync } from 'node:fs'
|
|
3
|
+
import { dirname, join, resolve } from 'node:path'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
import { spawnSync } from 'node:child_process'
|
|
6
6
|
|
|
7
|
-
const dir = resolve(process.argv[2] ?? 'octane-xplat-app')
|
|
7
|
+
const dir = resolve(process.argv[2] ?? 'octane-xplat-app')
|
|
8
8
|
|
|
9
9
|
if (existsSync(dir) && readdirSync(dir).length > 0) {
|
|
10
|
-
console.error(`✗ ${dir} exists and is not empty`)
|
|
11
|
-
process.exit(1)
|
|
10
|
+
console.error(`✗ ${dir} exists and is not empty`)
|
|
11
|
+
process.exit(1)
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const template = join(dirname(fileURLToPath(import.meta.url)), 'template')
|
|
15
|
-
cpSync(template, dir, { recursive: true })
|
|
14
|
+
const template = join(dirname(fileURLToPath(import.meta.url)), 'template')
|
|
15
|
+
cpSync(template, dir, { recursive: true })
|
|
16
16
|
// npm packs .gitignore as a renamed file or drops it — ship it undotted.
|
|
17
|
-
try {
|
|
18
|
-
|
|
17
|
+
try {
|
|
18
|
+
renameSync(join(dir, 'gitignore'), join(dir, '.gitignore'))
|
|
19
|
+
} catch {}
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
console.log(`\n✓ scaffolded ${dir}`)
|
|
22
|
+
|
|
23
|
+
const install = spawnSync('pnpm', ['install'], { cwd: dir, stdio: 'inherit' })
|
|
21
24
|
if (install.status !== 0) {
|
|
22
|
-
console.log(`\nInstall didn't finish (pnpm missing?). To run manually:`)
|
|
23
|
-
console.log(` cd ${dir}\n pnpm install\n pnpm dev`)
|
|
24
|
-
process.exit(install.status ?? 1)
|
|
25
|
+
console.log(`\nInstall didn't finish (pnpm missing?). To run manually:`)
|
|
26
|
+
console.log(` cd ${dir}\n pnpm install\n pnpm dev`)
|
|
27
|
+
process.exit(install.status ?? 1)
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
console.log('\n✓ installed — starting dev server (Ctrl+C to stop)\n')
|
|
28
|
-
spawnSync('pnpm', ['dev'], { cwd: dir, stdio: 'inherit' })
|
|
30
|
+
console.log('\n✓ installed — starting dev server (Ctrl+C to stop)\n')
|
|
31
|
+
spawnSync('pnpm', ['dev'], { cwd: dir, stdio: 'inherit' })
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-octane-xplat",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"type": "module",
|
|
3
|
+
"version": "0.4.0",
|
|
5
4
|
"description": "Scaffold a minimal @octane-xplat/ui app — one Octane codebase for web + iOS + Android",
|
|
6
5
|
"bin": {
|
|
7
6
|
"create-octane-xplat": "./index.mjs"
|
|
@@ -10,6 +9,7 @@
|
|
|
10
9
|
"index.mjs",
|
|
11
10
|
"template"
|
|
12
11
|
],
|
|
12
|
+
"type": "module",
|
|
13
13
|
"publishConfig": {
|
|
14
14
|
"access": "public"
|
|
15
15
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"jsPlugins": ["@octane-xplat/lint/oxlint-plugin"],
|
|
3
|
+
"rules": {
|
|
4
|
+
"curly": "error",
|
|
5
|
+
"xplat/spacing": "error",
|
|
6
|
+
"xplat/no-dom-globals": "error",
|
|
7
|
+
"xplat/no-web-only-api": "error",
|
|
8
|
+
"xplat/element-vocabulary": "error",
|
|
9
|
+
"xplat/no-nativescript-import": "error",
|
|
10
|
+
"xplat/no-ns-deep-import": "error",
|
|
11
|
+
"xplat/no-native-dead-style": "error",
|
|
12
|
+
"xplat/no-line-height-unitless": "error",
|
|
13
|
+
"xplat/no-style-string": "error",
|
|
14
|
+
"xplat/no-unknown-class": "warn",
|
|
15
|
+
"xplat/no-ts-imports-tsrx": "error",
|
|
16
|
+
"xplat/signal-dollar-suffix": "error",
|
|
17
|
+
"xplat/require-signals-runtime": "warn",
|
|
18
|
+
"xplat/no-view-onpress": "error",
|
|
19
|
+
"xplat/no-console-debug": "error",
|
|
20
|
+
"xplat/hooks-in-plain-ts": "warn",
|
|
21
|
+
"xplat/native-pragma-first-line": "error",
|
|
22
|
+
"xplat/no-jsx-text-breakers": "error",
|
|
23
|
+
"xplat/no-root-logical-render": "error"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -1,122 +1,122 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
2
|
+
"images": [
|
|
3
|
+
{
|
|
4
|
+
"size": "20x20",
|
|
5
|
+
"idiom": "iphone",
|
|
6
|
+
"filename": "icon-20@2x.png",
|
|
7
|
+
"scale": "2x"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"size": "20x20",
|
|
11
|
+
"idiom": "iphone",
|
|
12
|
+
"filename": "icon-20@3x.png",
|
|
13
|
+
"scale": "3x"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"size": "29x29",
|
|
17
|
+
"idiom": "iphone",
|
|
18
|
+
"filename": "icon-29.png",
|
|
19
|
+
"scale": "1x"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"size": "29x29",
|
|
23
|
+
"idiom": "iphone",
|
|
24
|
+
"filename": "icon-29@2x.png",
|
|
25
|
+
"scale": "2x"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"size": "29x29",
|
|
29
|
+
"idiom": "iphone",
|
|
30
|
+
"filename": "icon-29@3x.png",
|
|
31
|
+
"scale": "3x"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"size": "40x40",
|
|
35
|
+
"idiom": "iphone",
|
|
36
|
+
"filename": "icon-40@2x.png",
|
|
37
|
+
"scale": "2x"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"size": "40x40",
|
|
41
|
+
"idiom": "iphone",
|
|
42
|
+
"filename": "icon-40@3x.png",
|
|
43
|
+
"scale": "3x"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"size": "60x60",
|
|
47
|
+
"idiom": "iphone",
|
|
48
|
+
"filename": "icon-60@2x.png",
|
|
49
|
+
"scale": "2x"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"size": "60x60",
|
|
53
|
+
"idiom": "iphone",
|
|
54
|
+
"filename": "icon-60@3x.png",
|
|
55
|
+
"scale": "3x"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"size": "20x20",
|
|
59
|
+
"idiom": "ipad",
|
|
60
|
+
"filename": "icon-20.png",
|
|
61
|
+
"scale": "1x"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"size": "20x20",
|
|
65
|
+
"idiom": "ipad",
|
|
66
|
+
"filename": "icon-20@2x.png",
|
|
67
|
+
"scale": "2x"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"size": "29x29",
|
|
71
|
+
"idiom": "ipad",
|
|
72
|
+
"filename": "icon-29.png",
|
|
73
|
+
"scale": "1x"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"size": "29x29",
|
|
77
|
+
"idiom": "ipad",
|
|
78
|
+
"filename": "icon-29@2x.png",
|
|
79
|
+
"scale": "2x"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"size": "40x40",
|
|
83
|
+
"idiom": "ipad",
|
|
84
|
+
"filename": "icon-40.png",
|
|
85
|
+
"scale": "1x"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"size": "40x40",
|
|
89
|
+
"idiom": "ipad",
|
|
90
|
+
"filename": "icon-40@2x.png",
|
|
91
|
+
"scale": "2x"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"size": "76x76",
|
|
95
|
+
"idiom": "ipad",
|
|
96
|
+
"filename": "icon-76.png",
|
|
97
|
+
"scale": "1x"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"size": "76x76",
|
|
101
|
+
"idiom": "ipad",
|
|
102
|
+
"filename": "icon-76@2x.png",
|
|
103
|
+
"scale": "2x"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"size": "83.5x83.5",
|
|
107
|
+
"idiom": "ipad",
|
|
108
|
+
"filename": "icon-83.5@2x.png",
|
|
109
|
+
"scale": "2x"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"size": "1024x1024",
|
|
113
|
+
"idiom": "ios-marketing",
|
|
114
|
+
"filename": "icon-1024.png",
|
|
115
|
+
"scale": "1x"
|
|
116
|
+
}
|
|
117
|
+
],
|
|
118
|
+
"info": {
|
|
119
|
+
"version": 1,
|
|
120
|
+
"author": "xcode"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
2
|
+
"info": {
|
|
3
|
+
"version": 1,
|
|
4
|
+
"author": "xcode"
|
|
5
|
+
}
|
|
6
|
+
}
|
package/template/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
2
|
+
"images": [
|
|
3
|
+
{
|
|
4
|
+
"idiom": "universal",
|
|
5
|
+
"filename": "LaunchScreen-AspectFill.png",
|
|
6
|
+
"scale": "1x"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"idiom": "universal",
|
|
10
|
+
"filename": "LaunchScreen-AspectFill@2x.png",
|
|
11
|
+
"scale": "2x"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"idiom": "universal",
|
|
15
|
+
"filename": "LaunchScreen-AspectFill@3x.png",
|
|
16
|
+
"scale": "3x"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"info": {
|
|
20
|
+
"version": 1,
|
|
21
|
+
"author": "xcode"
|
|
22
|
+
}
|
|
23
|
+
}
|
package/template/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
2
|
+
"images": [
|
|
3
|
+
{
|
|
4
|
+
"idiom": "universal",
|
|
5
|
+
"filename": "LaunchScreen-Center.png",
|
|
6
|
+
"scale": "1x"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"idiom": "universal",
|
|
10
|
+
"filename": "LaunchScreen-Center@2x.png",
|
|
11
|
+
"scale": "2x"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"idiom": "universal",
|
|
15
|
+
"filename": "LaunchScreen-Center@3x.png",
|
|
16
|
+
"scale": "3x"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"info": {
|
|
20
|
+
"version": 1,
|
|
21
|
+
"author": "xcode"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
"images": [
|
|
3
|
+
{ "filename": "octane.png", "idiom": "universal", "scale": "1x" },
|
|
4
|
+
{ "filename": "octane@2x.png", "idiom": "universal", "scale": "2x" },
|
|
5
|
+
{ "filename": "octane@3x.png", "idiom": "universal", "scale": "3x" }
|
|
6
|
+
],
|
|
7
|
+
"info": { "author": "xcode", "version": 1 }
|
|
8
8
|
}
|
package/template/index.html
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>octane-xplat app</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="root"></div>
|
|
10
|
+
<script type="module" src="/src/main.web.tsrx"></script>
|
|
11
|
+
</body>
|
|
12
12
|
</html>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { NativeScriptConfig } from '@nativescript/core'
|
|
1
|
+
import { NativeScriptConfig } from '@nativescript/core'
|
|
2
2
|
|
|
3
3
|
export default {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} as NativeScriptConfig
|
|
4
|
+
id: 'org.nativescript.octanexplat',
|
|
5
|
+
appPath: 'src',
|
|
6
|
+
appResourcesPath: 'App_Resources',
|
|
7
|
+
android: {
|
|
8
|
+
v8Flags: '--expose_gc',
|
|
9
|
+
markingMode: 'none',
|
|
10
|
+
},
|
|
11
|
+
bundler: 'vite',
|
|
12
|
+
bundlerConfigPath: 'vite.config.native.mts',
|
|
13
|
+
} as NativeScriptConfig
|
package/template/package.json
CHANGED
|
@@ -1,37 +1,42 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
2
|
+
"name": "octane-xplat-app",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "src/index.native.ts",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"xplat": "xplat",
|
|
8
|
+
"dev": "vite",
|
|
9
|
+
"dev:ios": "ns run ios",
|
|
10
|
+
"dev:android": "ns run android",
|
|
11
|
+
"build": "vite build",
|
|
12
|
+
"build:ios": "ns build ios",
|
|
13
|
+
"build:android": "ns build android",
|
|
14
|
+
"lint": "xplat-lint",
|
|
15
|
+
"lint:fix": "xplat-lint --fix",
|
|
16
|
+
"typecheck": "tsrx-tsc --noEmit && tsrx-tsc --noEmit -p tsconfig.native.json"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@nativescript-community/octane": "0.2.1",
|
|
20
|
+
"@nativescript-community/ui-canvas": "4.6.52",
|
|
21
|
+
"@nativescript-community/ui-svg": "0.2.24",
|
|
22
|
+
"@nativescript/core": "9.1.2",
|
|
23
|
+
"@octane-xplat/ui": "^0.4.0",
|
|
24
|
+
"@valor/nativescript-websockets": "2.0.3",
|
|
25
|
+
"octane": "0.4.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@nativescript-community/vite-octane": "0.2.1",
|
|
29
|
+
"@nativescript/android": "9.1.1",
|
|
30
|
+
"@nativescript/ios": "9.1.0",
|
|
31
|
+
"@nativescript/types": "9.0.0",
|
|
32
|
+
"@nativescript/vite": "8.0.11",
|
|
33
|
+
"@octane-xplat/cli": "^0.4.0",
|
|
34
|
+
"@octane-xplat/lint": "^0.1.0",
|
|
35
|
+
"@octanejs/vite-plugin": "0.1.58",
|
|
36
|
+
"@tsrx/typescript-plugin": "0.4.7",
|
|
37
|
+
"oxlint": "^1.74.0",
|
|
38
|
+
"nativescript": "9.1.1",
|
|
39
|
+
"typescript": "5.9.3",
|
|
40
|
+
"vite": "8.3.0"
|
|
41
|
+
}
|
|
37
42
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// Native entry — the iOS/Android twin of main.web.tsrx. Same App.tsrx,
|
|
2
2
|
// different shell: a Frame hosting a Page that renders the universal root.
|
|
3
|
-
import { Application, Frame, Page } from '@nativescript/core'
|
|
4
|
-
import { renderNativeScriptApp } from '@nativescript-community/octane'
|
|
5
|
-
import { App } from './App.tsrx'
|
|
6
|
-
import '@octane-xplat/ui/theme/tokens.css'
|
|
7
|
-
import './style.css'
|
|
3
|
+
import { Application, Frame, Page } from '@nativescript/core'
|
|
4
|
+
import { renderNativeScriptApp } from '@nativescript-community/octane'
|
|
5
|
+
import { App } from './App.tsrx'
|
|
6
|
+
import '@octane-xplat/ui/theme/tokens.css'
|
|
7
|
+
import './style.css'
|
|
8
8
|
|
|
9
9
|
const entry = {
|
|
10
10
|
create: () => {
|
|
@@ -12,14 +12,14 @@ const entry = {
|
|
|
12
12
|
// window root doubles as the 'root' stack with no registration;
|
|
13
13
|
// named stacks come from TabSpec.stack or registerStack. Route
|
|
14
14
|
// pushes also need registerScreens({name: Component}) at boot.
|
|
15
|
-
const frame = new Frame()
|
|
16
|
-
const page = new Page()
|
|
17
|
-
page.actionBarHidden = true
|
|
18
|
-
renderNativeScriptApp(page, App)
|
|
19
|
-
frame.navigate({ create: () => page })
|
|
20
|
-
return frame
|
|
15
|
+
const frame = new Frame()
|
|
16
|
+
const page = new Page()
|
|
17
|
+
page.actionBarHidden = true
|
|
18
|
+
renderNativeScriptApp(page, App)
|
|
19
|
+
frame.navigate({ create: () => page })
|
|
20
|
+
return frame
|
|
21
21
|
},
|
|
22
|
-
}
|
|
22
|
+
}
|
|
23
23
|
|
|
24
24
|
// Under the vite dev session the placeholder bootstrap has already run
|
|
25
25
|
// Application.run(), and a module-graph reload re-evaluates this entry.
|
|
@@ -27,7 +27,7 @@ const entry = {
|
|
|
27
27
|
// (iOS core handles the placeholder handoff internally); resetRootView is
|
|
28
28
|
// the documented way to swap the root of a running app.
|
|
29
29
|
if (Application.started) {
|
|
30
|
-
Application.resetRootView(entry)
|
|
30
|
+
Application.resetRootView(entry)
|
|
31
31
|
} else {
|
|
32
|
-
Application.run(entry)
|
|
32
|
+
Application.run(entry)
|
|
33
33
|
}
|
package/template/src/style.css
CHANGED
|
@@ -68,6 +68,7 @@ body {
|
|
|
68
68
|
color: var(--color-on-primary);
|
|
69
69
|
padding: 10px 20px;
|
|
70
70
|
border-radius: 10px;
|
|
71
|
+
corner-shape: squircle;
|
|
71
72
|
font-size: 20px;
|
|
72
73
|
}
|
|
73
74
|
|
|
@@ -76,6 +77,7 @@ body {
|
|
|
76
77
|
color: var(--color-on-primary);
|
|
77
78
|
padding: 6px 14px;
|
|
78
79
|
border-radius: 14px;
|
|
80
|
+
corner-shape: squircle;
|
|
79
81
|
font-size: 14px;
|
|
80
82
|
}
|
|
81
83
|
|
package/template/tsconfig.json
CHANGED
|
@@ -1,85 +1,8 @@
|
|
|
1
|
-
import { defineConfig
|
|
2
|
-
import {
|
|
3
|
-
import { nativeScriptRenderer } from '@nativescript-community/octane/config';
|
|
1
|
+
import { defineConfig } from 'vite'
|
|
2
|
+
import { xplatNative } from '@octane-xplat/cli/vite'
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
* and the device silently stays stale. Warn once when a dev session was
|
|
11
|
-
* fetched but no client ever attached.
|
|
12
|
-
*/
|
|
13
|
-
function nsHmrClientWatchdog(): Plugin {
|
|
14
|
-
return {
|
|
15
|
-
name: 'ns-hmr-client-watchdog',
|
|
16
|
-
configureServer(server) {
|
|
17
|
-
let everConnected = false;
|
|
18
|
-
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
19
|
-
// Hook the raw 'request' event — middlewares.use() appends after the
|
|
20
|
-
// ns plugin's session handler, which ends the response without next(),
|
|
21
|
-
// so a connect middleware never observes /__ns_dev__/session at all.
|
|
22
|
-
server.httpServer?.on('request', (req) => {
|
|
23
|
-
if (!everConnected && req.url?.startsWith('/__ns_dev__/session')) {
|
|
24
|
-
clearTimeout(timer);
|
|
25
|
-
timer = setTimeout(() => {
|
|
26
|
-
if (!everConnected) {
|
|
27
|
-
console.warn(
|
|
28
|
-
'[ns-hmr-client-watchdog] the app fetched its dev session ' +
|
|
29
|
-
'but no /ns-hmr websocket client connected — edits will not ' +
|
|
30
|
-
'reach the device. Check that @valor/nativescript-websockets ' +
|
|
31
|
-
'is installed, `adb reverse tcp:<port>` covers this vite port ' +
|
|
32
|
-
'(physical Android), and the device log for hmr-client errors.',
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
}, 15_000);
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
server.httpServer?.on('upgrade', (req) => {
|
|
39
|
-
if (req.url?.startsWith('/ns-hmr')) {
|
|
40
|
-
everConnected = true;
|
|
41
|
-
clearTimeout(timer);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// The native build (iOS/Android). @octane-xplat/ui resolves through the
|
|
49
|
-
// package's `native` export condition → compiled dist/native — no .tsrx
|
|
50
|
-
// leaves needed from node_modules, so the renderer rule covers src/ only.
|
|
51
|
-
export default defineConfig(({ mode }) =>
|
|
52
|
-
mergeConfig(
|
|
53
|
-
octaneConfig(
|
|
54
|
-
{ mode },
|
|
55
|
-
{
|
|
56
|
-
octane: {
|
|
57
|
-
renderers: {
|
|
58
|
-
registry: { nativescript: nativeScriptRenderer },
|
|
59
|
-
rules: [
|
|
60
|
-
{ include: 'src/**/*.{ts,tsx,tsrx}', renderer: 'nativescript' },
|
|
61
|
-
],
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
),
|
|
66
|
-
{
|
|
67
|
-
plugins: [nsHmrClientWatchdog()],
|
|
68
|
-
resolve: {
|
|
69
|
-
conditions: ['native'],
|
|
70
|
-
// The deps-bundle scanner sees source-level 'octane' imports
|
|
71
|
-
// before the compiler retargets hooks — without this it vendors
|
|
72
|
-
// the DOM runtime. Exact match only.
|
|
73
|
-
alias: [{ find: /^octane$/, replacement: 'octane/universal/native' }],
|
|
74
|
-
preserveSymlinks: false,
|
|
75
|
-
// Suffix chain (first match wins): .ios/.android → .native → shared.
|
|
76
|
-
extensions: [
|
|
77
|
-
'.ios.tsrx', '.android.tsrx', '.native.tsrx', '.tsrx',
|
|
78
|
-
'.ios.tsx', '.android.tsx', '.native.tsx', '.tsx',
|
|
79
|
-
'.ios.ts', '.android.ts', '.native.ts', '.mjs', '.mts', '.ts',
|
|
80
|
-
'.jsx', '.js', '.json',
|
|
81
|
-
],
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
),
|
|
85
|
-
);
|
|
4
|
+
// The shared preset owns the renderer rules, octane→universal/native alias,
|
|
5
|
+
// suffix extension chain, deps-bundle plugin exclusions, the HMR watchdog,
|
|
6
|
+
// and the px→dip CSS rewrite. App-specific additions go through the second
|
|
7
|
+
// argument's `extra` (or mergeConfig).
|
|
8
|
+
export default defineConfig(({ mode }) => xplatNative(mode))
|
package/template/vite.config.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { defineConfig } from 'vite'
|
|
2
|
-
import { octane } from '@octanejs/vite-plugin'
|
|
1
|
+
import { defineConfig } from 'vite'
|
|
2
|
+
import { octane } from '@octanejs/vite-plugin'
|
|
3
3
|
|
|
4
4
|
// The web build. For native (iOS/Android), the same source runs through
|
|
5
5
|
// @nativescript-community/vite-octane with `conditions: ['native']` and the
|
|
@@ -12,10 +12,17 @@ export default defineConfig({
|
|
|
12
12
|
conditions: ['web'],
|
|
13
13
|
// Suffix chain (first match wins): .web → shared → fallback.
|
|
14
14
|
extensions: [
|
|
15
|
-
'.web.tsrx',
|
|
16
|
-
'.
|
|
17
|
-
'.web.
|
|
18
|
-
'.
|
|
15
|
+
'.web.tsrx',
|
|
16
|
+
'.tsrx',
|
|
17
|
+
'.web.tsx',
|
|
18
|
+
'.tsx',
|
|
19
|
+
'.web.ts',
|
|
20
|
+
'.mjs',
|
|
21
|
+
'.mts',
|
|
22
|
+
'.ts',
|
|
23
|
+
'.jsx',
|
|
24
|
+
'.js',
|
|
25
|
+
'.json',
|
|
19
26
|
],
|
|
20
27
|
},
|
|
21
|
-
})
|
|
28
|
+
})
|