@synopackageland/templates 0.41.4 → 0.42.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/CHANGELOG.md +11 -0
- package/README.md +9 -7
- package/package.json +5 -1
- package/templates/_shared/AGENTS.md +11 -11
- package/templates/_shared/package.json +4 -3
- package/templates/_shared/pnpm-lock.yaml +1636 -0
- package/templates/_shared/pnpm-workspace.yaml +2 -0
- package/templates/_shared/third-party-notices.mjs +75 -9
- package/templates/binary/README.md +3 -3
- package/templates/compose/README.md +3 -3
- package/templates/compose/dsm-package.yaml +1 -1
- package/templates/native-go/README.md +6 -6
- package/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +1 -1
- package/templates/native-go/backend/go.mod +1 -1
- package/templates/native-go/backend/go.sum +2 -2
- package/templates/native-go-vue/README.md +10 -10
- package/templates/native-go-vue/frontend/DESIGN.md +3 -3
- package/templates/native-go-vue/frontend/package.json +6 -4
- package/templates/native-go-vue/frontend/pnpm-lock.yaml +2269 -0
- package/templates/native-go-vue/frontend/pnpm-workspace.yaml +2 -0
- package/templates/native-node/README.md +8 -8
- package/templates/native-node/backend/app/package.json +2 -1
- package/templates/native-node/backend/app/pnpm-workspace.yaml +2 -0
- package/templates/native-node/backend/package.json +2 -1
- package/templates/native-node/backend/pnpm-lock.yaml +207 -0
- package/templates/native-node/dsm-package.yaml +2 -2
- package/templates/native-node-vue/README.md +9 -9
- package/templates/native-python/README.md +4 -4
- package/templates/native-python/dsm-package.yaml +1 -1
- package/templates/native-python-vue/README.md +9 -9
- package/templates/native-rust/README.md +4 -4
- package/templates/native-rust/backend/Cargo.lock +2 -2
- package/templates/native-rust/backend/Cargo.toml +1 -1
- package/templates/native-rust-delegate/backend/Cargo.lock +2 -2
- package/templates/native-rust-delegate/backend/Cargo.toml +1 -1
- package/templates/native-rust-vue/README.md +9 -9
- package/templates/native-go-vue/frontend/package-lock.json +0 -3115
- package/templates/native-node/backend/package-lock.json +0 -59
|
@@ -1,24 +1,90 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join, resolve } from 'node:path';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
import { parseAllDocuments } from 'yaml';
|
|
3
5
|
|
|
4
6
|
const OWNED = ['THIRD_PARTY_NOTICES.txt', 'inventory.json', 'UI-LICENSE', 'UI-THIRD_PARTY.md'];
|
|
5
7
|
|
|
8
|
+
function productionPackages(root) {
|
|
9
|
+
if (!existsSync(join(root, 'pnpm-lock.yaml'))) {
|
|
10
|
+
const lock = JSON.parse(readFileSync(join(root, 'package-lock.json'), 'utf8'));
|
|
11
|
+
if (lock.lockfileVersion < 2 || !lock.packages) throw new Error('Notice generation requires a v2/v3 npm lockfile');
|
|
12
|
+
return Object.entries(lock.packages).filter(([path, entry]) => path && !entry.dev)
|
|
13
|
+
.map(([path, entry]) => [path, entry, join(root, path)]);
|
|
14
|
+
}
|
|
15
|
+
const documents = parseAllDocuments(readFileSync(join(root, 'pnpm-lock.yaml'), 'utf8'));
|
|
16
|
+
if (documents.some(document => document.errors.length)) throw new Error('Invalid pnpm notice lockfile');
|
|
17
|
+
const lock = documents.at(-1)?.toJSON();
|
|
18
|
+
if (String(lock.lockfileVersion) !== '9.0' || !lock.importers?.['.'] || !lock.snapshots)
|
|
19
|
+
throw new Error('Notice generation requires a pnpm lockfile with importers and snapshots');
|
|
20
|
+
const importer = lock.importers['.'];
|
|
21
|
+
const manifest = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'));
|
|
22
|
+
// Keep the inventory's logical paths stable across package-manager layouts.
|
|
23
|
+
// Conflicting transitive versions remain beneath their owning dependency.
|
|
24
|
+
const versions = new Map();
|
|
25
|
+
for (const key of Object.keys(lock.packages ?? {})) {
|
|
26
|
+
const match = /^((?:@[^/]+\/)?[^@]+)@(.+)$/.exec(key);
|
|
27
|
+
if (!match) continue;
|
|
28
|
+
const [, name, version] = match;
|
|
29
|
+
const set = versions.get(name) ?? new Set();
|
|
30
|
+
set.add(version);
|
|
31
|
+
versions.set(name, set);
|
|
32
|
+
}
|
|
33
|
+
for (const group of ['dependencies', 'optionalDependencies'])
|
|
34
|
+
for (const [name, spec] of Object.entries(manifest[group] ?? {}))
|
|
35
|
+
if (importer[group]?.[name]?.specifier !== spec) throw new Error('Notice lockfile is out of date; run pnpm install');
|
|
36
|
+
const queue = [];
|
|
37
|
+
const enqueue = (entries, parent, path, optional = false) => {
|
|
38
|
+
for (const [name, ref] of Object.entries(entries ?? {}))
|
|
39
|
+
queue.push({name, ref: typeof ref === 'string' ? ref : ref.version, parent, path, optional});
|
|
40
|
+
};
|
|
41
|
+
enqueue(importer.dependencies, root, '');
|
|
42
|
+
enqueue(importer.optionalDependencies, root, '', true);
|
|
43
|
+
const seen = new Set(), paths = new Set(), entries = [];
|
|
44
|
+
while (queue.length) {
|
|
45
|
+
const {name, ref, parent, path: parentPath, optional} = queue.shift();
|
|
46
|
+
const key = `${name}@${ref}`;
|
|
47
|
+
const direct = importer.dependencies?.[name] ?? importer.optionalDependencies?.[name];
|
|
48
|
+
const nested = parentPath && versions.get(name)?.size > 1 && direct?.version !== ref;
|
|
49
|
+
const seenKey = nested ? `${key} from ${parent}` : key;
|
|
50
|
+
if (seen.has(seenKey)) continue;
|
|
51
|
+
seen.add(seenKey);
|
|
52
|
+
const snapshot = lock.snapshots[key];
|
|
53
|
+
const packageKey = key.replace(/\(.*$/, '');
|
|
54
|
+
const entry = lock.packages?.[packageKey];
|
|
55
|
+
if (!snapshot || !entry) throw new Error(`Missing locked notice dependency: ${key}`);
|
|
56
|
+
const search = createRequire(join(parent, 'package.json')).resolve.paths(name) ?? [];
|
|
57
|
+
const installed = search.map(dir => join(dir, name)).find(dir => existsSync(join(dir, 'package.json')));
|
|
58
|
+
if (!installed && optional) continue;
|
|
59
|
+
if (!installed) throw new Error(`Missing installed notice dependency: ${name}; run pnpm install --frozen-lockfile`);
|
|
60
|
+
const dir = realpathSync(installed);
|
|
61
|
+
let path = nested ? `${parentPath}/node_modules/${name}` : `node_modules/${name}`;
|
|
62
|
+
if (paths.has(path)) path = `${parentPath}/node_modules/${name}`;
|
|
63
|
+
paths.add(path);
|
|
64
|
+
// A local tarball ref names a file; pnpm records its version separately.
|
|
65
|
+
const version = entry.resolution?.type === 'directory'
|
|
66
|
+
? JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')).version
|
|
67
|
+
: entry.version ?? ref.replace(/\(.*$/, '');
|
|
68
|
+
entries.push([path, {version, integrity: entry.resolution?.integrity}, dir]);
|
|
69
|
+
enqueue(snapshot.dependencies, dir, path);
|
|
70
|
+
enqueue(snapshot.optionalDependencies, dir, path, true);
|
|
71
|
+
}
|
|
72
|
+
return entries;
|
|
73
|
+
}
|
|
74
|
+
|
|
6
75
|
// Conservative inventory of every locked production dependency, including
|
|
7
76
|
// dependencies tree-shaken from the bundle. Build tools marked dev are omitted.
|
|
8
77
|
// Read actual upstream license/notice files, never synthesize license text from
|
|
9
|
-
// SPDX metadata.
|
|
78
|
+
// SPDX metadata. Install the exact lock before this runs.
|
|
10
79
|
export function writeThirdPartyNotices(root, output, { ui = false } = {}) {
|
|
11
|
-
|
|
12
|
-
if (lock.lockfileVersion < 2 || !lock.packages) throw new Error('Notice generation requires a v2/v3 npm lockfile');
|
|
80
|
+
root = resolve(root);
|
|
13
81
|
const inventory = [];
|
|
14
82
|
const sections = [];
|
|
15
83
|
let uiFiles;
|
|
16
|
-
for (const [path, entry] of
|
|
17
|
-
if (!path || entry.dev) continue;
|
|
84
|
+
for (const [path, entry, dir] of productionPackages(root).sort(([a], [b]) => a.localeCompare(b, 'en'))) {
|
|
18
85
|
if (!/^node_modules\//.test(path) || path.split('/').includes('..') || entry.link) throw new Error(`Unsupported notice package path: ${path}`);
|
|
19
|
-
const dir = join(root, path);
|
|
20
86
|
const pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'));
|
|
21
|
-
if (pkg.version !== entry.version) throw new Error(`Notice version mismatch: ${path}; run
|
|
87
|
+
if (pkg.version !== entry.version) throw new Error(`Notice version mismatch: ${path}; run pnpm install --frozen-lockfile`);
|
|
22
88
|
const files = readdirSync(dir, { withFileTypes: true })
|
|
23
89
|
.filter(f => f.isFile() && /^(licen[sc]e|copying|notice|copyright)([.-]|$)/i.test(f.name))
|
|
24
90
|
.map(f => f.name).sort();
|
|
@@ -7,12 +7,12 @@ Copy `.env.example` to the ignored `.env` only for optional AI tests; keep real
|
|
|
7
7
|
From the project root, install the test tools before running the optional tests:
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
pnpm install --prod=false
|
|
11
|
+
pnpm test
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
`NODE_ENV=production` skips devDependencies; `test:local` needs the CLI.
|
|
15
|
-
After committing the generated root lockfile, use `
|
|
15
|
+
After committing the generated root lockfile, use `pnpm install --frozen-lockfile --prod=false`.
|
|
16
16
|
The scaffold provides example prebuilt binaries; replace them with your own
|
|
17
17
|
Linux binaries before packaging. See `AGENTS.md` for the package workflow.
|
|
18
18
|
|
|
@@ -7,12 +7,12 @@ Copy `.env.example` to the ignored `.env` only for optional AI tests; keep real
|
|
|
7
7
|
From the project root, install the test tools before running the optional tests:
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
pnpm install --prod=false
|
|
11
|
+
pnpm test
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
`NODE_ENV=production` skips devDependencies; `test:local` needs the CLI.
|
|
15
|
-
After committing the generated root lockfile, use `
|
|
15
|
+
After committing the generated root lockfile, use `pnpm install --frozen-lockfile --prod=false`.
|
|
16
16
|
Configure the upstream image and its real readiness endpoint before
|
|
17
17
|
`test:local`; see `AGENTS.md` for the Compose packaging workflow.
|
|
18
18
|
|
|
@@ -23,7 +23,7 @@ compose:
|
|
|
23
23
|
web: {service: web, port: 8080, health: {path: /, status: 200}}
|
|
24
24
|
network: {egress: isolated}
|
|
25
25
|
identity_gateway:
|
|
26
|
-
sdk: 0.53.
|
|
26
|
+
sdk: 0.53.16
|
|
27
27
|
mode: none
|
|
28
28
|
listen: {http: 28000}
|
|
29
29
|
# Web Apps default to new-page through the shared app-launch resolver.
|
|
@@ -36,13 +36,13 @@ Copy `.env.example` to the ignored `.env` only for optional AI tests; keep real
|
|
|
36
36
|
From the project root, install the test tools before running the optional tests:
|
|
37
37
|
|
|
38
38
|
```sh
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
pnpm install --prod=false
|
|
40
|
+
pnpm test
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
`NODE_ENV=production` skips devDependencies; `test:local` needs the CLI.
|
|
44
|
-
After committing the generated root lockfile, use `
|
|
45
|
-
Before `
|
|
44
|
+
After committing the generated root lockfile, use `pnpm install --frozen-lockfile --prod=false`.
|
|
45
|
+
Before `pnpm run test:local`, prepare the backend and, for Vue, build the
|
|
46
46
|
frontend using the steps below and the backend section in `AGENTS.md`, then
|
|
47
47
|
run `synopkgland ctl generate`.
|
|
48
48
|
|
|
@@ -282,7 +282,7 @@ ui:
|
|
|
282
282
|
dir: web/dist
|
|
283
283
|
build:
|
|
284
284
|
cwd: web
|
|
285
|
-
command: [
|
|
285
|
+
command: [pnpm, run, build]
|
|
286
286
|
```
|
|
287
287
|
|
|
288
288
|
The build must emit `app.js` (a classic script that registers `mount`) or
|
|
@@ -490,7 +490,7 @@ select `ui: false`. For an upstream web panel with no SDK UI, set `ui: false`
|
|
|
490
490
|
in `synology/dsm-package.yaml` and configure `identity_gateway` for the panel.
|
|
491
491
|
Remove `synology/ui/` (or `synology/frontend/` for Vue),
|
|
492
492
|
`synology/tests/e2e/`, `synology/e2e.config.ts` and
|
|
493
|
-
`synology/e2e.ai.config.ts`, and remove the `e2e:*`
|
|
493
|
+
`synology/e2e.ai.config.ts`, and remove the `e2e:*` package scripts.
|
|
494
494
|
Keep `synology/backend/`, `synology/i18n/messages/`, `synology/operations.json` and
|
|
495
495
|
the local/ctl tests: the entry gate still needs the backend and message catalogs.
|
|
496
496
|
Read `synopkgland skill show upstream-fork` and
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
github.com/synopackageland/syno-pkg-land-sdk v0.53.
|
|
2
|
-
github.com/synopackageland/syno-pkg-land-sdk v0.53.
|
|
1
|
+
github.com/synopackageland/syno-pkg-land-sdk v0.53.16 h1:i4FCBCpOr7ma31zFathuS2QLpCWa13y3v9rWvlg+AfE=
|
|
2
|
+
github.com/synopackageland/syno-pkg-land-sdk v0.53.16/go.mod h1:JMfenGwAhlVgGUtoSQFA9XRbtN8Zcs+0xdrOaaam+Fg=
|
|
3
3
|
golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
|
|
4
4
|
golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
|
@@ -14,13 +14,13 @@ Copy `.env.example` to the ignored `.env` only for optional AI tests; keep real
|
|
|
14
14
|
From the project root, install the test tools before running the optional tests:
|
|
15
15
|
|
|
16
16
|
```sh
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
pnpm install --prod=false
|
|
18
|
+
pnpm test
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
`NODE_ENV=production` skips devDependencies; `test:local` needs the CLI.
|
|
22
|
-
After committing the generated root lockfile, use `
|
|
23
|
-
Before `
|
|
22
|
+
After committing the generated root lockfile, use `pnpm install --frozen-lockfile --prod=false`.
|
|
23
|
+
Before `pnpm run test:local`, prepare the backend and, for Vue, build the
|
|
24
24
|
frontend using the steps below and the backend section in `AGENTS.md`, then
|
|
25
25
|
run `synopkgland ctl generate`.
|
|
26
26
|
|
|
@@ -37,9 +37,9 @@ See the [fork guide](https://github.com/synopackageland/syno-pkg-land-templates#
|
|
|
37
37
|
|
|
38
38
|
```sh
|
|
39
39
|
cd frontend
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
pnpm install --frozen-lockfile --prod=false
|
|
41
|
+
pnpm test
|
|
42
|
+
pnpm run build
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
The base app reads package status and edits the package greeting through
|
|
@@ -139,7 +139,7 @@ Read `synopkgland skill show ui-vue` for direct Vue component work and
|
|
|
139
139
|
`synopkgland skill show ui-json` for optional declarative specs and their
|
|
140
140
|
validate/render workflow. The existing host/backend lifecycle remains in place.
|
|
141
141
|
|
|
142
|
-
For UI discovery, run `
|
|
143
|
-
`
|
|
142
|
+
For UI discovery, run `pnpm exec syno-pkg-land-ui catalog --json` and
|
|
143
|
+
`pnpm exec syno-pkg-land-ui describe Button --json` from the installed frontend.
|
|
144
144
|
Read its prompt and exported Vue docs/types before choosing component APIs.
|
|
145
|
-
Use `syno-pkg-land-ui` directly in
|
|
145
|
+
Use `syno-pkg-land-ui` directly in package scripts; keep AI guidance version-independent.
|
|
@@ -22,10 +22,10 @@ spacing:
|
|
|
22
22
|
|
|
23
23
|
Read `AGENTS.md` at the project root and `synopkgland skill show ui-vue` before UI edits.
|
|
24
24
|
|
|
25
|
-
For UI discovery, run `
|
|
26
|
-
`
|
|
25
|
+
For UI discovery, run `pnpm exec syno-pkg-land-ui catalog --json` and
|
|
26
|
+
`pnpm exec syno-pkg-land-ui describe Button --json` from the installed frontend.
|
|
27
27
|
Read its prompt and exported Vue docs/types before choosing component APIs.
|
|
28
|
-
Use `syno-pkg-land-ui` directly in
|
|
28
|
+
Use `syno-pkg-land-ui` directly in package scripts; keep AI guidance version-independent.
|
|
29
29
|
|
|
30
30
|
## Overview
|
|
31
31
|
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"@lucide/vue": "1.48.0",
|
|
11
|
-
"@synopackageland/sdk": "~0.53.
|
|
12
|
-
"@synopackageland/ui": "~0.
|
|
11
|
+
"@synopackageland/sdk": "~0.53.16",
|
|
12
|
+
"@synopackageland/ui": "~0.25.2",
|
|
13
13
|
"vue": "3.5.43"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
"typescript": "5.9.3",
|
|
19
19
|
"vite": "7.3.6",
|
|
20
20
|
"vitest": "4.1.11",
|
|
21
|
-
"vue-tsc": "3.3.11"
|
|
22
|
-
|
|
21
|
+
"vue-tsc": "3.3.11",
|
|
22
|
+
"yaml": "^2.9.1"
|
|
23
|
+
},
|
|
24
|
+
"packageManager": "pnpm@12.18.0"
|
|
23
25
|
}
|