ossplate 0.1.0 → 0.1.1
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 +23 -4
- package/bin/darwin-arm64/ossplate +0 -0
- package/package.json +2 -2
- package/scaffold/.github/workflows/publish-npm.yml +21 -2
- package/scaffold/CONTRIBUTING.md +2 -0
- package/scaffold/README.md +39 -34
- package/scaffold/assets/illustrations/chestplate.svg +46 -0
- package/scaffold/core-rs/Cargo.lock +1 -1
- package/scaffold/core-rs/Cargo.toml +2 -2
- package/scaffold/core-rs/src/main.rs +33 -14
- package/scaffold/docs/README.md +3 -0
- package/scaffold/docs/customizing-the-template.md +9 -9
- package/scaffold/docs/testing.md +2 -0
- package/scaffold/docs/upgrade-plan.md +61 -224
- package/scaffold/ossplate.toml +1 -1
- package/scaffold/wrapper-js/README.md +23 -4
- package/scaffold/wrapper-js/bin/darwin-arm64/ossplate +0 -0
- package/scaffold/wrapper-js/package-lock.json +2 -2
- package/scaffold/wrapper-js/package.json +2 -2
- package/scaffold/wrapper-py/README.md +23 -4
- package/scaffold/wrapper-py/pyproject.toml +2 -2
- package/scaffold/wrapper-py/src/ossplate/bin/darwin-arm64/ossplate +0 -0
- package/dist/index.d.ts +0 -10
- package/dist/index.js +0 -56
package/README.md
CHANGED
|
@@ -1,7 +1,26 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Ossplate
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`ossplate` helps you start and maintain a project that ships the same CLI through Rust, npm, and PyPI.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Use it to:
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- create a new scaffolded project
|
|
8
|
+
- initialize an existing directory
|
|
9
|
+
- validate project identity and metadata
|
|
10
|
+
- keep owned files in sync
|
|
11
|
+
|
|
12
|
+
Common commands:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
ossplate version
|
|
16
|
+
ossplate create <target>
|
|
17
|
+
ossplate init --path <dir>
|
|
18
|
+
ossplate validate
|
|
19
|
+
ossplate sync --check
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Learn more:
|
|
23
|
+
|
|
24
|
+
- [Main documentation](../docs/README.md)
|
|
25
|
+
- [Testing guide](../docs/testing.md)
|
|
26
|
+
- [Architecture](../docs/architecture.md)
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"bin": {
|
|
4
4
|
"ossplate": "bin/ossplate.js"
|
|
5
5
|
},
|
|
6
|
-
"description": "
|
|
6
|
+
"description": "Build one project, ship it everywhere.",
|
|
7
7
|
"devDependencies": {
|
|
8
8
|
"@types/node": "^24.6.0",
|
|
9
9
|
"typescript": "^5.9.3"
|
|
@@ -39,5 +39,5 @@
|
|
|
39
39
|
"test": "npm run build && node --test test/cli.test.js"
|
|
40
40
|
},
|
|
41
41
|
"type": "module",
|
|
42
|
-
"version": "0.1.
|
|
42
|
+
"version": "0.1.1"
|
|
43
43
|
}
|
|
@@ -38,8 +38,27 @@ jobs:
|
|
|
38
38
|
- if: steps.published.outputs.already != 'true'
|
|
39
39
|
run: npm ci
|
|
40
40
|
working-directory: ./wrapper-js
|
|
41
|
-
-
|
|
42
|
-
|
|
41
|
+
- name: Publish to npm
|
|
42
|
+
if: steps.published.outputs.already != 'true'
|
|
43
43
|
working-directory: ./wrapper-js
|
|
44
44
|
env:
|
|
45
45
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
46
|
+
run: |
|
|
47
|
+
set +e
|
|
48
|
+
npm publish --access public --provenance 2>&1 | tee npm-publish.log
|
|
49
|
+
status=${PIPESTATUS[0]}
|
|
50
|
+
set -e
|
|
51
|
+
if [ "$status" -eq 0 ]; then
|
|
52
|
+
echo "::notice title=npm::published with OIDC trusted publishing."
|
|
53
|
+
exit 0
|
|
54
|
+
fi
|
|
55
|
+
if [ -z "${NODE_AUTH_TOKEN:-}" ]; then
|
|
56
|
+
echo "::error title=npm::OIDC publish failed and NPM_TOKEN is not configured."
|
|
57
|
+
exit "$status"
|
|
58
|
+
fi
|
|
59
|
+
if grep -qiE "already exists|cannot publish over|previously published" npm-publish.log; then
|
|
60
|
+
echo "::notice title=npm::package version already exists; skipping."
|
|
61
|
+
exit 0
|
|
62
|
+
fi
|
|
63
|
+
echo "::warning title=npm::OIDC publish failed; retrying with NPM_TOKEN fallback."
|
|
64
|
+
npm publish --access public
|
package/scaffold/CONTRIBUTING.md
CHANGED
|
@@ -21,6 +21,8 @@ cargo run --manifest-path core-rs/Cargo.toml -- sync --check
|
|
|
21
21
|
cargo run --manifest-path core-rs/Cargo.toml -- sync
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
Release workflow guidance lives in [`docs/releases.md`](./docs/releases.md).
|
|
25
|
+
|
|
24
26
|
Current ownership model:
|
|
25
27
|
|
|
26
28
|
- `ossplate.toml` is the canonical identity source
|
package/scaffold/README.md
CHANGED
|
@@ -1,36 +1,32 @@
|
|
|
1
1
|
<!-- ossplate:readme-identity:start -->
|
|
2
2
|
# Ossplate
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
Build one project, ship it everywhere.
|
|
5
5
|
<!-- ossplate:readme-identity:end -->
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+

|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
- a thin npm wrapper in [`wrapper-js/`](./wrapper-js)
|
|
11
|
-
- a thin Python wrapper in [`wrapper-py/`](./wrapper-py)
|
|
12
|
-
- normal `push` / `pull_request` CI
|
|
13
|
-
- rerun-safe publish workflows for npm, PyPI, and Cargo
|
|
14
|
-
- setup and upgrade docs in [`docs/`](./docs/README.md)
|
|
9
|
+
`ossplate` helps you start and maintain a project that ships the same CLI through Rust, npm, and PyPI.
|
|
15
10
|
|
|
16
|
-
|
|
11
|
+
It gives you a working baseline with:
|
|
17
12
|
|
|
18
|
-
|
|
13
|
+
- one real core CLI
|
|
14
|
+
- thin JavaScript and Python wrappers
|
|
15
|
+
- release-ready workflows for Cargo, npm, and PyPI
|
|
16
|
+
- a scaffold you can create, adopt, and keep in sync
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
## What It Does
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
Use `ossplate` when you want a single command-line tool to exist cleanly in multiple ecosystems without maintaining three separate implementations.
|
|
23
21
|
|
|
24
|
-
|
|
25
|
-
cargo run --manifest-path core-rs/Cargo.toml -- validate
|
|
26
|
-
cargo run --manifest-path core-rs/Cargo.toml -- sync --check
|
|
27
|
-
cargo run --manifest-path core-rs/Cargo.toml -- create ../my-new-project
|
|
28
|
-
cargo run --manifest-path core-rs/Cargo.toml -- init --path ../existing-project
|
|
29
|
-
```
|
|
22
|
+
It can:
|
|
30
23
|
|
|
31
|
-
|
|
24
|
+
- create a new scaffolded project
|
|
25
|
+
- initialize an existing directory with the expected structure
|
|
26
|
+
- validate project identity and metadata
|
|
27
|
+
- synchronize the files it owns
|
|
32
28
|
|
|
33
|
-
|
|
29
|
+
## Quick Start
|
|
34
30
|
|
|
35
31
|
```bash
|
|
36
32
|
cargo run --manifest-path core-rs/Cargo.toml -- create ../my-new-project \
|
|
@@ -44,29 +40,38 @@ cargo run --manifest-path core-rs/Cargo.toml -- create ../my-new-project \
|
|
|
44
40
|
--command "my-project"
|
|
45
41
|
```
|
|
46
42
|
|
|
47
|
-
|
|
43
|
+
Then check that everything is aligned:
|
|
48
44
|
|
|
49
|
-
|
|
45
|
+
```bash
|
|
46
|
+
cargo run --manifest-path core-rs/Cargo.toml -- validate
|
|
47
|
+
cargo run --manifest-path core-rs/Cargo.toml -- sync --check
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Core Commands
|
|
50
51
|
|
|
51
52
|
```bash
|
|
52
|
-
|
|
53
|
+
ossplate version
|
|
54
|
+
ossplate create <target>
|
|
55
|
+
ossplate init --path <dir>
|
|
56
|
+
ossplate validate
|
|
57
|
+
ossplate sync --check
|
|
53
58
|
```
|
|
54
59
|
|
|
55
|
-
|
|
60
|
+
The same command surface is available through the Rust binary and the packaged JS/Python wrappers.
|
|
56
61
|
|
|
57
|
-
##
|
|
62
|
+
## Why It’s Useful
|
|
58
63
|
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
- JS and Python artifact tests prove installed distributions can run `version`, `create`, and `validate`
|
|
64
|
+
- You keep one source of truth for CLI behavior.
|
|
65
|
+
- You avoid drift between Rust, npm, and PyPI releases.
|
|
66
|
+
- You get a real scaffold instead of a fake demo project.
|
|
67
|
+
- You can publish with modern registry workflows instead of assembling release plumbing from scratch.
|
|
64
68
|
|
|
65
|
-
##
|
|
69
|
+
## Learn More
|
|
66
70
|
|
|
67
|
-
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
71
|
+
- [Documentation](./docs/README.md)
|
|
72
|
+
- [Testing Guide](./docs/testing.md)
|
|
73
|
+
- [Release Guide](./docs/releases.md)
|
|
74
|
+
- [Architecture](./docs/architecture.md)
|
|
70
75
|
|
|
71
76
|
## License
|
|
72
77
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 420" role="img" aria-labelledby="title desc">
|
|
2
|
+
<title id="title">Ossplate chestplate illustration</title>
|
|
3
|
+
<desc id="desc">A bronze chestplate with shoulder guards on a warm background.</desc>
|
|
4
|
+
<defs>
|
|
5
|
+
<linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
6
|
+
<stop offset="0%" stop-color="#f7ecdd"/>
|
|
7
|
+
<stop offset="100%" stop-color="#dcb88b"/>
|
|
8
|
+
</linearGradient>
|
|
9
|
+
<linearGradient id="metal" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
10
|
+
<stop offset="0%" stop-color="#ddaf68"/>
|
|
11
|
+
<stop offset="50%" stop-color="#b77735"/>
|
|
12
|
+
<stop offset="100%" stop-color="#7b491c"/>
|
|
13
|
+
</linearGradient>
|
|
14
|
+
<linearGradient id="rim" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
15
|
+
<stop offset="0%" stop-color="#fff0bf"/>
|
|
16
|
+
<stop offset="100%" stop-color="#a05d24"/>
|
|
17
|
+
</linearGradient>
|
|
18
|
+
<linearGradient id="highlight" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
19
|
+
<stop offset="0%" stop-color="#fff8de" stop-opacity="0.95"/>
|
|
20
|
+
<stop offset="100%" stop-color="#fff8de" stop-opacity="0"/>
|
|
21
|
+
</linearGradient>
|
|
22
|
+
<filter id="shadow" x="-20%" y="-20%" width="140%" height="160%">
|
|
23
|
+
<feDropShadow dx="0" dy="16" stdDeviation="12" flood-color="#673d18" flood-opacity="0.28"/>
|
|
24
|
+
</filter>
|
|
25
|
+
</defs>
|
|
26
|
+
|
|
27
|
+
<rect width="720" height="420" fill="url(#bg)"/>
|
|
28
|
+
<circle cx="110" cy="84" r="58" fill="#fff7de" opacity="0.4"/>
|
|
29
|
+
<circle cx="607" cy="314" r="76" fill="#a86e33" opacity="0.12"/>
|
|
30
|
+
|
|
31
|
+
<g filter="url(#shadow)" transform="translate(150 28)">
|
|
32
|
+
<path d="M151 46c12-18 27-29 59-34 16-2 42-3 59-3s43 1 59 3c32 5 47 16 59 34l24 35c7 10 4 24-6 31l-22 16c-8 6-19 7-29 2l-27-13v90c0 60-26 102-58 129-32 26-64 39-91 45-27-6-59-19-91-45-32-27-58-69-58-129v-90l-27 13c-10 5-21 4-29-2l-22-16c-10-7-13-21-6-31z" fill="url(#metal)"/>
|
|
33
|
+
<path d="M151 46c12-18 27-29 59-34 16-2 42-3 59-3s43 1 59 3c32 5 47 16 59 34l24 35c7 10 4 24-6 31l-22 16c-8 6-19 7-29 2l-27-13v90c0 60-26 102-58 129-32 26-64 39-91 45-27-6-59-19-91-45-32-27-58-69-58-129v-90l-27 13c-10 5-21 4-29-2l-22-16c-10-7-13-21-6-31z" fill="none" stroke="#6b4118" stroke-width="10" stroke-linejoin="round"/>
|
|
34
|
+
<path d="M210 52c11-14 26-20 44-22 15-2 29-2 46-2s31 0 46 2c18 2 33 8 44 22l15 20c-41 18-92 27-105 29-13-2-64-11-105-29z" fill="#c78741" opacity="0.88"/>
|
|
35
|
+
<path d="M126 74l32 16c10 5 21 4 30-2l20-13c18 9 43 16 72 20v204c-56-15-121-61-121-158V93c0-8-12-13-33-19z" fill="#845022" opacity="0.34"/>
|
|
36
|
+
<path d="M474 74l-32 16c-10 5-21 4-30-2l-20-13c-18 9-43 16-72 20v204c56-15 121-61 121-158V93c0-8 12-13 33-19z" fill="#f0c27a" opacity="0.2"/>
|
|
37
|
+
<path d="M300 92v214" stroke="#6b4118" stroke-width="8" stroke-linecap="round" opacity="0.82"/>
|
|
38
|
+
<path d="M196 134c29 12 65 18 104 18s75-6 104-18" stroke="#6b4118" stroke-width="7" stroke-linecap="round" opacity="0.72"/>
|
|
39
|
+
<path d="M206 215c24 9 56 14 94 14s70-5 94-14" stroke="#6b4118" stroke-width="6" stroke-linecap="round" opacity="0.62"/>
|
|
40
|
+
<path d="M235 42c19 10 40 16 65 19-13 10-23 24-29 41-25-4-48-12-68-25 7-16 17-27 32-35z" fill="url(#highlight)" opacity="0.72"/>
|
|
41
|
+
<path d="M300 61c25-3 46-9 65-19 15 8 25 19 32 35-20 13-43 21-68 25-6-17-16-31-29-41z" fill="url(#highlight)" opacity="0.5"/>
|
|
42
|
+
<path d="M147 62l-41 58c-5 7-3 17 4 22l18 13c5 4 12 4 18 1l41-19-9-53c-2-11-14-21-31-22z" fill="url(#rim)" opacity="0.95"/>
|
|
43
|
+
<path d="M453 62l41 58c5 7 3 17-4 22l-18 13c-5 4-12 4-18 1l-41-19 9-53c2-11 14-21 31-22z" fill="url(#rim)" opacity="0.95"/>
|
|
44
|
+
<path d="M214 310c26 14 56 23 86 28 30-5 60-14 86-28" stroke="#f3d39a" stroke-width="6" stroke-linecap="round" opacity="0.45"/>
|
|
45
|
+
</g>
|
|
46
|
+
</svg>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "ossplate"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.1"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
authors = ["Stef <stefdevscore@github.com>"]
|
|
6
|
-
description = "
|
|
6
|
+
description = "Build one project, ship it everywhere."
|
|
7
7
|
license = "Unlicense"
|
|
8
8
|
readme = "../README.md"
|
|
9
9
|
repository = "https://github.com/stefdevscore/ossplate"
|
|
@@ -1040,18 +1040,37 @@ fn validate_wrapper_readme(
|
|
|
1040
1040
|
}
|
|
1041
1041
|
}
|
|
1042
1042
|
|
|
1043
|
-
fn render_wrapper_readme(
|
|
1043
|
+
fn render_wrapper_readme(_language: &str, config: &ToolConfig) -> String {
|
|
1044
1044
|
format!(
|
|
1045
|
-
r#"# {
|
|
1045
|
+
r#"# {name}
|
|
1046
1046
|
|
|
1047
|
-
|
|
1047
|
+
`{command}` helps you start and maintain a project that ships the same CLI through Rust, npm, and PyPI.
|
|
1048
1048
|
|
|
1049
|
-
|
|
1049
|
+
Use it to:
|
|
1050
1050
|
|
|
1051
|
-
|
|
1051
|
+
- create a new scaffolded project
|
|
1052
|
+
- initialize an existing directory
|
|
1053
|
+
- validate project identity and metadata
|
|
1054
|
+
- keep owned files in sync
|
|
1055
|
+
|
|
1056
|
+
Common commands:
|
|
1057
|
+
|
|
1058
|
+
```bash
|
|
1059
|
+
{command} version
|
|
1060
|
+
{command} create <target>
|
|
1061
|
+
{command} init --path <dir>
|
|
1062
|
+
{command} validate
|
|
1063
|
+
{command} sync --check
|
|
1064
|
+
```
|
|
1065
|
+
|
|
1066
|
+
Learn more:
|
|
1067
|
+
|
|
1068
|
+
- [Main documentation](../docs/README.md)
|
|
1069
|
+
- [Testing guide](../docs/testing.md)
|
|
1070
|
+
- [Architecture](../docs/architecture.md)
|
|
1052
1071
|
"#,
|
|
1053
|
-
language = language,
|
|
1054
1072
|
name = config.project.name,
|
|
1073
|
+
command = config.packages.command,
|
|
1055
1074
|
)
|
|
1056
1075
|
}
|
|
1057
1076
|
|
|
@@ -1266,7 +1285,7 @@ mod tests {
|
|
|
1266
1285
|
let root = make_fixture_root();
|
|
1267
1286
|
fs::write(
|
|
1268
1287
|
root.join("wrapper-js/package.json"),
|
|
1269
|
-
"{\n \"name\": \"bad\",\n \"description\": \"
|
|
1288
|
+
"{\n \"name\": \"bad\",\n \"description\": \"Build one project, ship it everywhere.\",\n \"bin\": { \"ossplate\": \"bin/ossplate.js\" },\n \"author\": \"Stef <stefdevscore@github.com>\",\n \"license\": \"Unlicense\",\n \"repository\": { \"url\": \"https://github.com/stefdevscore/ossplate\" }\n}\n",
|
|
1270
1289
|
)
|
|
1271
1290
|
.unwrap();
|
|
1272
1291
|
let output = validate_repo(&root).unwrap();
|
|
@@ -1386,7 +1405,7 @@ mod tests {
|
|
|
1386
1405
|
target.join("core-rs/Cargo.toml"),
|
|
1387
1406
|
r#"[package]
|
|
1388
1407
|
name = "bad-core"
|
|
1389
|
-
version = "0.1.
|
|
1408
|
+
version = "0.1.1"
|
|
1390
1409
|
"#,
|
|
1391
1410
|
)
|
|
1392
1411
|
.unwrap();
|
|
@@ -1440,7 +1459,7 @@ version = "0.1.0"
|
|
|
1440
1459
|
fs::write(
|
|
1441
1460
|
root.join("README.md"),
|
|
1442
1461
|
original.replace(
|
|
1443
|
-
"
|
|
1462
|
+
"Build one project, ship it everywhere",
|
|
1444
1463
|
"Changed identity text",
|
|
1445
1464
|
),
|
|
1446
1465
|
)
|
|
@@ -1449,7 +1468,7 @@ version = "0.1.0"
|
|
|
1449
1468
|
sync_repo(&root, false).unwrap();
|
|
1450
1469
|
let synced = fs::read_to_string(root.join("README.md")).unwrap();
|
|
1451
1470
|
assert!(synced.contains("## What This Tool Gives You"));
|
|
1452
|
-
assert!(synced.contains("
|
|
1471
|
+
assert!(synced.contains("Build one project, ship it everywhere"));
|
|
1453
1472
|
}
|
|
1454
1473
|
|
|
1455
1474
|
#[test]
|
|
@@ -1499,7 +1518,7 @@ version = "0.1.0"
|
|
|
1499
1518
|
let config = r#"[project]
|
|
1500
1519
|
name = "Ossplate"
|
|
1501
1520
|
slug = "ossplate"
|
|
1502
|
-
description = "
|
|
1521
|
+
description = "Build one project, ship it everywhere."
|
|
1503
1522
|
repository = "https://github.com/stefdevscore/ossplate"
|
|
1504
1523
|
license = "Unlicense"
|
|
1505
1524
|
|
|
@@ -1522,7 +1541,7 @@ command = "ossplate"
|
|
|
1522
1541
|
root.join("core-rs/Cargo.toml"),
|
|
1523
1542
|
r#"[package]
|
|
1524
1543
|
name = "ossplate"
|
|
1525
|
-
version = "0.1.
|
|
1544
|
+
version = "0.1.1"
|
|
1526
1545
|
edition = "2021"
|
|
1527
1546
|
authors = ["Stef <stefdevscore@github.com>"]
|
|
1528
1547
|
description = "A practical baseline for shipping one project across Cargo, npm, and PyPI without starting from scratch every time."
|
|
@@ -1535,14 +1554,14 @@ homepage = "https://github.com/stefdevscore/ossplate"
|
|
|
1535
1554
|
.unwrap();
|
|
1536
1555
|
fs::write(
|
|
1537
1556
|
root.join("wrapper-js/package.json"),
|
|
1538
|
-
"{\n \"name\": \"ossplate\",\n \"description\": \"
|
|
1557
|
+
"{\n \"name\": \"ossplate\",\n \"description\": \"Build one project, ship it everywhere.\",\n \"bin\": { \"ossplate\": \"bin/ossplate.js\" },\n \"author\": \"Stef <stefdevscore@github.com>\",\n \"license\": \"Unlicense\",\n \"repository\": { \"url\": \"https://github.com/stefdevscore/ossplate\" }\n}\n",
|
|
1539
1558
|
)
|
|
1540
1559
|
.unwrap();
|
|
1541
1560
|
fs::write(
|
|
1542
1561
|
root.join("wrapper-py/pyproject.toml"),
|
|
1543
1562
|
r#"[project]
|
|
1544
1563
|
name = "ossplate"
|
|
1545
|
-
description = "
|
|
1564
|
+
description = "Build one project, ship it everywhere."
|
|
1546
1565
|
license = { text = "Unlicense" }
|
|
1547
1566
|
authors = [
|
|
1548
1567
|
{ name = "Stef", email = "stefdevscore@github.com" }
|
package/scaffold/docs/README.md
CHANGED
|
@@ -5,7 +5,9 @@ This docs area explains how to use `ossplate` as a real tool for validating, syn
|
|
|
5
5
|
## Start Here
|
|
6
6
|
|
|
7
7
|
- [Customizing The Template](./customizing-the-template.md)
|
|
8
|
+
- [Architecture](./architecture.md)
|
|
8
9
|
- [Testing Guide](./testing.md)
|
|
10
|
+
- [Release Guide](./releases.md)
|
|
9
11
|
- [Phase 1 Contract](./phase-1-contract.md)
|
|
10
12
|
- [Upgrade Plan](./upgrade-plan.md)
|
|
11
13
|
- `ossplate validate` checks owned metadata drift
|
|
@@ -18,4 +20,5 @@ This docs area explains how to use `ossplate` as a real tool for validating, syn
|
|
|
18
20
|
- the canonical config and command surface
|
|
19
21
|
- the required rename and customization surface before first release
|
|
20
22
|
- the layered testing and packaging workflow
|
|
23
|
+
- the release operator flow and rerun-safe publish expectations
|
|
21
24
|
- the phased plan for turning this tool into a broader scaffold product
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Adopting The Scaffold
|
|
2
2
|
|
|
3
|
-
Use this checklist after creating or cloning a scaffold managed by `ossplate`. The goal is to
|
|
3
|
+
Use this checklist after creating or cloning a scaffold managed by `ossplate`. The goal is to adopt the scaffold under your own project identity and then use the tool to keep owned metadata in sync.
|
|
4
4
|
|
|
5
5
|
## Canonical Source Of Truth
|
|
6
6
|
|
|
@@ -24,18 +24,18 @@ It currently owns:
|
|
|
24
24
|
|
|
25
25
|
## Validation Policy
|
|
26
26
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
27
|
+
- Template-source identities are allowed only when the repository is discussing `ossplate` itself.
|
|
28
|
+
- Inherited identities are not allowed in shipping metadata or package-facing docs for an adopted project.
|
|
29
29
|
- Command and package naming must be chosen intentionally before release.
|
|
30
30
|
- Author, repository, and license fields must be set explicitly rather than inherited accidentally.
|
|
31
31
|
|
|
32
32
|
The current validator follows this policy through the Rust core rather than a standalone JS rule engine.
|
|
33
33
|
|
|
34
|
-
## Required
|
|
34
|
+
## Required Identity Changes
|
|
35
35
|
|
|
36
|
-
Replace these defaults before reuse:
|
|
36
|
+
Replace these inherited defaults before reuse:
|
|
37
37
|
|
|
38
|
-
| Surface | Current
|
|
38
|
+
| Surface | Current scaffold value | Where it lives |
|
|
39
39
|
| --- | --- | --- |
|
|
40
40
|
| Rust crate name | `ossplate` | `core-rs/Cargo.toml` |
|
|
41
41
|
| npm package name | `ossplate` | `wrapper-js/package.json` |
|
|
@@ -43,7 +43,7 @@ Replace these defaults before reuse:
|
|
|
43
43
|
| CLI command | `ossplate` | `ossplate.toml`, `wrapper-js/package.json`, `wrapper-py/pyproject.toml` |
|
|
44
44
|
| Repository URL | `https://github.com/stefdevscore/ossplate` | Rust, npm, Python metadata |
|
|
45
45
|
| Author/email | `Stef <stefdevscore@github.com>` / `stefdevscore@github.com` | Rust, npm, Python metadata |
|
|
46
|
-
| Package-facing
|
|
46
|
+
| Package-facing scaffold branding | `ossplate` identity in wrapper docs | `wrapper-js/README.md`, `wrapper-py/README.md` |
|
|
47
47
|
|
|
48
48
|
## Files To Review
|
|
49
49
|
|
|
@@ -139,6 +139,6 @@ cargo run --manifest-path core-rs/Cargo.toml -- init \
|
|
|
139
139
|
|
|
140
140
|
This tool is trying to optimize for a real delivery baseline:
|
|
141
141
|
|
|
142
|
-
- CI should fail before
|
|
142
|
+
- CI should fail before inherited identity reaches a release path.
|
|
143
143
|
- package metadata should not be inherited by accident
|
|
144
144
|
- future phases can add richer scaffold creation and maintenance without first cleaning up metadata drift
|
package/scaffold/docs/testing.md
CHANGED
|
@@ -69,3 +69,5 @@ CI currently enforces:
|
|
|
69
69
|
- Python tests and wheel build
|
|
70
70
|
|
|
71
71
|
The current artifact tests are the required release-confidence floor. Future phases can add broader platform coverage or slower end-to-end suites without changing the basic layered model.
|
|
72
|
+
|
|
73
|
+
For release-specific operator steps, version bumps, and rerun-safe publish expectations, see [`docs/releases.md`](./releases.md).
|
|
@@ -1,251 +1,88 @@
|
|
|
1
|
-
# Ossplate
|
|
1
|
+
# Ossplate Roadmap
|
|
2
2
|
|
|
3
|
-
##
|
|
4
|
-
|
|
5
|
-
Turn `ossplate` from a minimal multi-registry demo into a production-ready scaffold tool with:
|
|
6
|
-
|
|
7
|
-
- one canonical core program
|
|
8
|
-
- real wrapper parity across Rust, TypeScript/JavaScript, and Python
|
|
9
|
-
- robust CI and publish workflows with explicit auth fallbacks
|
|
10
|
-
- layered testing guidance and enforcement
|
|
11
|
-
- a structure that can scale toward a hexagonal architecture shell
|
|
12
|
-
|
|
13
|
-
The product behavior is now real in the core maintenance and scaffold paths. Remaining work is about hardening, ergonomics, and release scale.
|
|
14
|
-
|
|
15
|
-
## Operating Principles
|
|
16
|
-
|
|
17
|
-
- Keep one source of truth for CLI behavior and output contracts.
|
|
18
|
-
- Prefer thin wrappers over duplicated implementations.
|
|
19
|
-
- Fail early when template placeholders were not replaced.
|
|
20
|
-
- Use OIDC where the registry path is configured and supported, with explicit token fallbacks elsewhere.
|
|
21
|
-
- Require install/build/test/package checks before any publish step.
|
|
22
|
-
- Keep the starter small, but not fake in the critical paths.
|
|
23
|
-
|
|
24
|
-
## Phase 0: Stabilize the Template Baseline
|
|
25
|
-
|
|
26
|
-
Purpose: make the current scaffold safe to evolve and hard to misuse.
|
|
27
|
-
|
|
28
|
-
### P0
|
|
29
|
-
|
|
30
|
-
- Add a release-readiness validator that fails on placeholder metadata.
|
|
31
|
-
- Validate package names, crate name, binary names, repository URLs, author fields, and obvious placeholder strings.
|
|
32
|
-
- Add a root documentation index under `docs/` so implementation docs have a stable home.
|
|
33
|
-
|
|
34
|
-
### P1
|
|
35
|
-
|
|
36
|
-
- Normalize naming conventions across Cargo, npm, and PyPI packages.
|
|
37
|
-
- Define the canonical command name and the expected wrapper naming pattern.
|
|
38
|
-
- Document the template customization surface:
|
|
39
|
-
project name, package ids, repo URL, author, license, binary name, description.
|
|
40
|
-
|
|
41
|
-
### P2
|
|
42
|
-
|
|
43
|
-
- Remove or tighten weak placeholder copy in README files.
|
|
44
|
-
- Add a checklist for creating a new project from the template.
|
|
45
|
-
|
|
46
|
-
### Exit Criteria
|
|
47
|
-
|
|
48
|
-
- A new maintainer can identify every required rename/customization step.
|
|
49
|
-
- CI can fail automatically if placeholder identity leaks into a release path.
|
|
50
|
-
|
|
51
|
-
## Phase 1: Establish the Canonical Core and Wrapper Parity
|
|
52
|
-
|
|
53
|
-
Purpose: stop treating each ecosystem as a separate product stub.
|
|
54
|
-
|
|
55
|
-
### P0
|
|
56
|
-
|
|
57
|
-
- Make the Rust binary the canonical executable implementation.
|
|
58
|
-
- Define a small, stable placeholder command contract:
|
|
59
|
-
`--help`, `version`, `health`, and one example command returning structured JSON.
|
|
60
|
-
- Convert the JavaScript package into a real wrapper around the packaged binary.
|
|
61
|
-
- Convert the Python package into a real wrapper around the packaged binary.
|
|
62
|
-
- Ensure wrappers preserve exit codes, stdout, and stderr from the core binary.
|
|
63
|
-
|
|
64
|
-
### P1
|
|
65
|
-
|
|
66
|
-
- Move `wrapper-js` source to TypeScript and publish built JavaScript artifacts.
|
|
67
|
-
- Add binary resolution logic for supported platforms in both wrappers.
|
|
68
|
-
- Add wrapper tests that assert parity against the core binary output contract.
|
|
69
|
-
|
|
70
|
-
### P2
|
|
71
|
-
|
|
72
|
-
- Add a small shared contract document covering commands, arguments, output, and error behavior.
|
|
73
|
-
- Add support for environment-based binary overrides for local development and debugging.
|
|
74
|
-
|
|
75
|
-
### Exit Criteria
|
|
76
|
-
|
|
77
|
-
- Rust, JS, and Python packages all exercise the same underlying behavior.
|
|
78
|
-
- Wrapper packages no longer maintain separate hand-written CLI logic.
|
|
79
|
-
|
|
80
|
-
## Phase 2: Production-Grade Quality Gates
|
|
81
|
-
|
|
82
|
-
Purpose: make the scaffold trustworthy before publish automation runs.
|
|
83
|
-
|
|
84
|
-
### P0
|
|
85
|
-
|
|
86
|
-
- Expand CI to enforce core quality gates in all three environments.
|
|
87
|
-
- Add Rust checks:
|
|
88
|
-
`cargo fmt --check`, `cargo clippy -- -D warnings`, `cargo test`.
|
|
89
|
-
- Add JS/TS checks:
|
|
90
|
-
install, typecheck, test, package dry-run.
|
|
91
|
-
- Add Python checks:
|
|
92
|
-
environment setup, tests, wheel/sdist build, install-from-built-artifact smoke test.
|
|
93
|
-
- Add a cross-package parity job that verifies wrappers match core contract behavior.
|
|
94
|
-
|
|
95
|
-
### P1
|
|
96
|
-
|
|
97
|
-
- Add artifact-level smoke tests for packaged npm and wheel outputs.
|
|
98
|
-
- Add a matrix strategy where it materially improves confidence for supported platforms.
|
|
99
|
-
- Make CI logs and job names intentionally clear for template adopters.
|
|
100
|
-
|
|
101
|
-
### P2
|
|
102
|
-
|
|
103
|
-
- Add optional local aggregate commands or scripts for running all checks consistently.
|
|
104
|
-
- Add a contributor quickstart for running the same quality gates outside CI.
|
|
105
|
-
|
|
106
|
-
### Exit Criteria
|
|
107
|
-
|
|
108
|
-
- A release candidate must pass formatting, linting, unit tests, packaging, and parity checks.
|
|
109
|
-
- Published artifacts are verified before publish jobs run.
|
|
110
|
-
|
|
111
|
-
## Phase 3: Robust Publishing with OIDC First and Concrete Fallbacks
|
|
112
|
-
|
|
113
|
-
Purpose: keep publishing reliable even when registry auth or registry behavior is imperfect.
|
|
114
|
-
|
|
115
|
-
### P0
|
|
116
|
-
|
|
117
|
-
- Keep publish workflows rerun-safe with published-version detection before attempting release.
|
|
118
|
-
- Use OIDC or trusted publishing where supported and configured.
|
|
119
|
-
- For the current `ossplate` baseline:
|
|
120
|
-
PyPI uses OIDC, Cargo uses OIDC with `CARGO_TOKEN` fallback, and npm uses `NPM_TOKEN`.
|
|
121
|
-
- Add explicit secret-based fallbacks:
|
|
122
|
-
`NPM_TOKEN`, PyPI API token, and `CARGO_REGISTRY_TOKEN`.
|
|
123
|
-
- Make auth mode selection visible in workflow logs.
|
|
124
|
-
- Preserve non-destructive handling of already-published versions.
|
|
125
|
-
|
|
126
|
-
### P1
|
|
127
|
-
|
|
128
|
-
- Document exact registry setup steps for both preferred and fallback auth modes.
|
|
129
|
-
- Add validation that publish jobs fail clearly when neither OIDC nor token auth is configured.
|
|
130
|
-
- Tighten registry-specific behavior:
|
|
131
|
-
npm public access, PyPI trusted publishing expectations, crates.io version detection and retry behavior.
|
|
132
|
-
|
|
133
|
-
### P2
|
|
134
|
-
|
|
135
|
-
- Add optional manual dispatch inputs for dry-run or targeted registry publish flows if they simplify maintenance.
|
|
136
|
-
- Add guidance for organizations that intentionally disable OIDC and standardize on tokens.
|
|
137
|
-
|
|
138
|
-
### Exit Criteria
|
|
139
|
-
|
|
140
|
-
- Publish workflows are understandable, rerunnable, and resilient.
|
|
141
|
-
- Auth failures are explicit and actionable rather than implicit or flaky.
|
|
142
|
-
|
|
143
|
-
## Phase 4: Layered Testing Guidance and Scaffolding
|
|
144
|
-
|
|
145
|
-
Purpose: teach adopters how to scale verification without overcomplicating the starter.
|
|
146
|
-
|
|
147
|
-
### P0
|
|
148
|
-
|
|
149
|
-
- Add docs for the default testing pyramid:
|
|
150
|
-
smoke, unit, integration/parity, and release verification.
|
|
151
|
-
- Define minimum required tests for any project generated from this template.
|
|
152
|
-
- Document how wrapper parity tests fit into the scaffold.
|
|
153
|
-
|
|
154
|
-
### P1
|
|
155
|
-
|
|
156
|
-
- Add optional docs for live end-to-end browser testing with Playwright when a generated project includes a web UI.
|
|
157
|
-
- Clarify that Playwright is not a default requirement for non-UI projects.
|
|
158
|
-
- Add example CI placement for smoke vs slower e2e suites.
|
|
159
|
-
|
|
160
|
-
### P2
|
|
161
|
-
|
|
162
|
-
- Add template examples of failure triage:
|
|
163
|
-
unit regression, packaging regression, publish regression, wrapper parity regression.
|
|
164
|
-
|
|
165
|
-
### Exit Criteria
|
|
166
|
-
|
|
167
|
-
- The testing strategy is clear enough that teams do not improvise incompatible structures from scratch.
|
|
168
|
-
- Optional e2e guidance exists without forcing UI assumptions onto every project.
|
|
169
|
-
|
|
170
|
-
## Phase 5: Architecture Shell and Scaling Docs
|
|
3
|
+
## Current State
|
|
171
4
|
|
|
172
|
-
|
|
5
|
+
`ossplate` is no longer a placeholder scaffold. It now ships as a real multi-registry tool with:
|
|
173
6
|
|
|
174
|
-
|
|
7
|
+
- a canonical Rust CLI
|
|
8
|
+
- thin npm and Python wrappers
|
|
9
|
+
- real `validate`, `sync`, `create`, and `init` commands
|
|
10
|
+
- curated scaffold payloads in installed wrapper artifacts
|
|
11
|
+
- CI quality gates across Rust, JS, and Python
|
|
12
|
+
- OIDC-first publishing for PyPI, Cargo, and npm, with token fallbacks where configured
|
|
175
13
|
|
|
176
|
-
|
|
177
|
-
domain, application, adapters, and delivery surfaces.
|
|
178
|
-
- Define where product logic belongs and where it should not live.
|
|
179
|
-
- Document wrappers as adapters rather than alternate implementations.
|
|
14
|
+
Published names are aligned as:
|
|
180
15
|
|
|
181
|
-
|
|
16
|
+
- crates.io: `ossplate`
|
|
17
|
+
- npm: `ossplate`
|
|
18
|
+
- PyPI: `ossplate`
|
|
19
|
+
- CLI: `ossplate`
|
|
182
20
|
|
|
183
|
-
|
|
184
|
-
- Link to the stronger internal reference material that informed this structure.
|
|
185
|
-
- Add ADR guidance if the template grows beyond a small starter.
|
|
21
|
+
## Completed
|
|
186
22
|
|
|
187
|
-
###
|
|
23
|
+
### Foundation
|
|
188
24
|
|
|
189
|
-
-
|
|
190
|
-
-
|
|
25
|
+
- Placeholder identity validation is wired into CI.
|
|
26
|
+
- `ossplate.toml` is the canonical identity source.
|
|
27
|
+
- Root docs, testing docs, customization docs, and release docs now exist.
|
|
191
28
|
|
|
192
|
-
|
|
29
|
+
### Product Surface
|
|
193
30
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
5. Phase 4
|
|
199
|
-
6. Phase 5
|
|
31
|
+
- Rust is the only source of product logic.
|
|
32
|
+
- JS and Python are thin wrappers around the packaged binary.
|
|
33
|
+
- The command surface is now real:
|
|
34
|
+
`version`, `validate`, `sync`, `create`, `init`.
|
|
200
35
|
|
|
201
|
-
|
|
36
|
+
### Packaging And Artifact Reality
|
|
202
37
|
|
|
203
|
-
-
|
|
204
|
-
-
|
|
205
|
-
-
|
|
206
|
-
- Phase 3 hardens release automation after the package surfaces are stable.
|
|
207
|
-
- Phase 4 and Phase 5 improve scale and adoption quality without blocking the core scaffold.
|
|
38
|
+
- Installed npm and Python artifacts carry the scaffold payload required by `create` and `init`.
|
|
39
|
+
- Scaffold payload staging is curated by manifest rather than broad repo-copy behavior.
|
|
40
|
+
- Artifact tests verify required content and exclude known non-shipping content.
|
|
208
41
|
|
|
209
|
-
|
|
42
|
+
### Quality Gates
|
|
210
43
|
|
|
211
|
-
|
|
44
|
+
- CI enforces Rust format, clippy, and tests.
|
|
45
|
+
- CI enforces JS build, tests, and package dry-run.
|
|
46
|
+
- CI enforces Python tests and wheel build.
|
|
47
|
+
- Wrapper parity and installed-artifact smoke paths are exercised.
|
|
48
|
+
- `./scripts/verify.sh` mirrors the local gate.
|
|
212
49
|
|
|
213
|
-
|
|
50
|
+
### Publishing
|
|
214
51
|
|
|
215
|
-
|
|
216
|
-
|
|
52
|
+
- Publish flows are rerun-safe.
|
|
53
|
+
- PyPI uses OIDC.
|
|
54
|
+
- Cargo uses OIDC with `CARGO_TOKEN` fallback.
|
|
55
|
+
- npm uses OIDC with `NPM_TOKEN` fallback.
|
|
56
|
+
- The release operator flow is documented in [`docs/releases.md`](./releases.md).
|
|
217
57
|
|
|
218
|
-
|
|
58
|
+
## Remaining Priorities
|
|
219
59
|
|
|
220
|
-
|
|
60
|
+
## P1
|
|
221
61
|
|
|
222
|
-
|
|
223
|
-
|
|
62
|
+
- Expand `sync` ownership carefully into a few more identity-only surfaces where bounded ownership is safe.
|
|
63
|
+
- Improve `validate` and `sync --check` output further if field-level drift becomes hard to read at scale.
|
|
64
|
+
- Add a short architecture note describing the current boundary:
|
|
65
|
+
Rust core as product logic, JS/Python as adapters, scaffold payload as distribution asset.
|
|
224
66
|
|
|
225
|
-
|
|
67
|
+
## P2
|
|
226
68
|
|
|
227
|
-
|
|
69
|
+
- Add optional guidance for generated projects that need browser-based live end-to-end tests.
|
|
70
|
+
- Add examples of failure triage for packaging, publish, and parity regressions.
|
|
71
|
+
- Tighten workflow/docs ownership boundaries further if more fields become sync-managed.
|
|
228
72
|
|
|
229
|
-
|
|
230
|
-
the scaffold becomes easier to adopt, extend, and scale across future projects.
|
|
73
|
+
## P3
|
|
231
74
|
|
|
232
|
-
|
|
75
|
+
- Add architecture-shell guidance for teams that want to scale generated projects into a fuller hexagonal layout.
|
|
76
|
+
- Add ADR guidance if the scaffold evolves into a broader product platform.
|
|
233
77
|
|
|
234
|
-
|
|
78
|
+
## Release Maintenance
|
|
235
79
|
|
|
236
|
-
-
|
|
237
|
-
-
|
|
238
|
-
-
|
|
239
|
-
- `ossplate.toml` is the canonical identity source for owned metadata surfaces
|
|
240
|
-
- installed npm and Python artifacts now carry the staged scaffold payload for `create` and `init`
|
|
241
|
-
- artifact smoke tests prove installed distributions can run `version`, `create`, and `validate`
|
|
242
|
-
- scaffold payload staging is now driven by an explicit curated manifest instead of a broad repo snapshot
|
|
243
|
-
- Python packaging stages distribution assets through its build hook
|
|
244
|
-
- CI now enforces Rust formatting and clippy alongside the existing test/package checks
|
|
80
|
+
- Refresh GitHub Actions dependencies ahead of the Node 20 runner deprecation.
|
|
81
|
+
- Keep trusted publishing and token fallback documentation aligned with real registry configuration.
|
|
82
|
+
- Keep release-version bumps aligned across Cargo, npm, and PyPI metadata.
|
|
245
83
|
|
|
246
|
-
## Next
|
|
84
|
+
## Suggested Next Work
|
|
247
85
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
- harden publish workflows with the OIDC-first fallback strategy from Phase 3
|
|
86
|
+
1. Decide whether `sync` should own any additional identity-only fields beyond the current bounded set.
|
|
87
|
+
2. Improve `validate` and `sync --check` if larger repos need richer drift output.
|
|
88
|
+
3. Add optional browser-e2e guidance for generated projects that include a UI.
|
package/scaffold/ossplate.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "Ossplate"
|
|
3
|
-
description = "
|
|
3
|
+
description = "Build one project, ship it everywhere."
|
|
4
4
|
repository = "https://github.com/stefdevscore/ossplate"
|
|
5
5
|
license = "Unlicense"
|
|
6
6
|
|
|
@@ -1,7 +1,26 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Ossplate
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`ossplate` helps you start and maintain a project that ships the same CLI through Rust, npm, and PyPI.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Use it to:
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- create a new scaffolded project
|
|
8
|
+
- initialize an existing directory
|
|
9
|
+
- validate project identity and metadata
|
|
10
|
+
- keep owned files in sync
|
|
11
|
+
|
|
12
|
+
Common commands:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
ossplate version
|
|
16
|
+
ossplate create <target>
|
|
17
|
+
ossplate init --path <dir>
|
|
18
|
+
ossplate validate
|
|
19
|
+
ossplate sync --check
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Learn more:
|
|
23
|
+
|
|
24
|
+
- [Main documentation](../docs/README.md)
|
|
25
|
+
- [Testing guide](../docs/testing.md)
|
|
26
|
+
- [Architecture](../docs/architecture.md)
|
|
Binary file
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ossplate",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "ossplate",
|
|
9
|
-
"version": "0.1.
|
|
9
|
+
"version": "0.1.1",
|
|
10
10
|
"license": "Unlicense",
|
|
11
11
|
"bin": {
|
|
12
12
|
"ossplate": "bin/ossplate.js"
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"bin": {
|
|
4
4
|
"ossplate": "bin/ossplate.js"
|
|
5
5
|
},
|
|
6
|
-
"description": "
|
|
6
|
+
"description": "Build one project, ship it everywhere.",
|
|
7
7
|
"devDependencies": {
|
|
8
8
|
"@types/node": "^24.6.0",
|
|
9
9
|
"typescript": "^5.9.3"
|
|
@@ -39,5 +39,5 @@
|
|
|
39
39
|
"test": "npm run build && node --test test/cli.test.js"
|
|
40
40
|
},
|
|
41
41
|
"type": "module",
|
|
42
|
-
"version": "0.1.
|
|
42
|
+
"version": "0.1.1"
|
|
43
43
|
}
|
|
@@ -1,7 +1,26 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Ossplate
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`ossplate` helps you start and maintain a project that ships the same CLI through Rust, npm, and PyPI.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Use it to:
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- create a new scaffolded project
|
|
8
|
+
- initialize an existing directory
|
|
9
|
+
- validate project identity and metadata
|
|
10
|
+
- keep owned files in sync
|
|
11
|
+
|
|
12
|
+
Common commands:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
ossplate version
|
|
16
|
+
ossplate create <target>
|
|
17
|
+
ossplate init --path <dir>
|
|
18
|
+
ossplate validate
|
|
19
|
+
ossplate sync --check
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Learn more:
|
|
23
|
+
|
|
24
|
+
- [Main documentation](../docs/README.md)
|
|
25
|
+
- [Testing guide](../docs/testing.md)
|
|
26
|
+
- [Architecture](../docs/architecture.md)
|
|
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ossplate"
|
|
7
|
-
version = "0.1.
|
|
8
|
-
description = "
|
|
7
|
+
version = "0.1.1"
|
|
8
|
+
description = "Build one project, ship it everywhere."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
11
11
|
license = { text = "Unlicense" }
|
|
Binary file
|
package/dist/index.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export declare function resolveOssplateBinary(options?: {
|
|
2
|
-
baseDir?: string;
|
|
3
|
-
platform?: NodeJS.Platform;
|
|
4
|
-
arch?: string;
|
|
5
|
-
}): string;
|
|
6
|
-
export declare function runOssplate(args?: string[], options?: {
|
|
7
|
-
baseDir?: string;
|
|
8
|
-
platform?: NodeJS.Platform;
|
|
9
|
-
arch?: string;
|
|
10
|
-
}): void;
|
package/dist/index.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { accessSync, constants } from "node:fs";
|
|
2
|
-
import { spawn } from "node:child_process";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { dirname, join } from "node:path";
|
|
5
|
-
import { arch as runtimeArch, platform as runtimePlatform } from "node:os";
|
|
6
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
const ENV_OVERRIDE = "OSSPLATE_BINARY";
|
|
8
|
-
const TEMPLATE_ROOT_ENV = "OSSPLATE_TEMPLATE_ROOT";
|
|
9
|
-
const TARGETS = {
|
|
10
|
-
darwin: { arm64: "darwin-arm64", x64: "darwin-x64" },
|
|
11
|
-
linux: { x64: "linux-x64" },
|
|
12
|
-
win32: { x64: "win32-x64" }
|
|
13
|
-
};
|
|
14
|
-
export function resolveOssplateBinary(options = {}) {
|
|
15
|
-
const envOverride = process.env[ENV_OVERRIDE];
|
|
16
|
-
if (envOverride) {
|
|
17
|
-
return envOverride;
|
|
18
|
-
}
|
|
19
|
-
const platform = options.platform ?? runtimePlatform();
|
|
20
|
-
const arch = options.arch ?? runtimeArch();
|
|
21
|
-
const target = TARGETS[platform]?.[arch];
|
|
22
|
-
if (!target) {
|
|
23
|
-
throw new Error(`Unsupported platform/arch: ${platform}/${arch}`);
|
|
24
|
-
}
|
|
25
|
-
const executable = platform === "win32" ? "ossplate.exe" : "ossplate";
|
|
26
|
-
const baseDir = options.baseDir ?? join(__dirname, "..");
|
|
27
|
-
const packagedPath = join(baseDir, "bin", target, executable);
|
|
28
|
-
assertExecutable(packagedPath);
|
|
29
|
-
return packagedPath;
|
|
30
|
-
}
|
|
31
|
-
export function runOssplate(args = [], options = {}) {
|
|
32
|
-
const binPath = resolveOssplateBinary(options);
|
|
33
|
-
const baseDir = options.baseDir ?? join(__dirname, "..");
|
|
34
|
-
const child = spawn(binPath, args, {
|
|
35
|
-
stdio: "inherit",
|
|
36
|
-
env: {
|
|
37
|
-
...process.env,
|
|
38
|
-
[TEMPLATE_ROOT_ENV]: process.env[TEMPLATE_ROOT_ENV] ?? join(baseDir, "scaffold")
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
child.on("exit", (code) => {
|
|
42
|
-
process.exit(code ?? 0);
|
|
43
|
-
});
|
|
44
|
-
child.on("error", (error) => {
|
|
45
|
-
console.error(`ossplate: ${error.message}`);
|
|
46
|
-
process.exit(1);
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
function assertExecutable(filePath) {
|
|
50
|
-
try {
|
|
51
|
-
accessSync(filePath, constants.X_OK);
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
throw new Error(`Bundled ossplate binary not found or not executable at ${filePath}`);
|
|
55
|
-
}
|
|
56
|
-
}
|