@tinycld/bootstrap 1.0.0 → 1.1.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/dist/bootstrap-tooling.js +96 -13
- package/dist/bootstrap-tooling.js.map +1 -1
- package/dist/index.js +41 -22
- package/dist/index.js.map +1 -1
- package/dist/layout.js +7 -20
- package/dist/layout.js.map +1 -1
- package/dist/link-package.js +77 -62
- package/dist/link-package.js.map +1 -1
- package/dist/prompts.js +3 -3
- package/dist/prompts.js.map +1 -1
- package/package.json +1 -1
- package/templates/full/package.json +7 -1
- package/templates/full/playwright.config.ts +20 -0
- package/templates/full/server/go.mod +2 -2
- package/templates/settings-only/package.json +6 -1
- package/templates/shared/.github/workflows/ci.yml +62 -38
- package/templates/shared/README.md +40 -29
- package/templates/shared/tsconfig.json +5 -14
- package/templates/shared/vitest.config.ts +16 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process';
|
|
2
|
-
import { existsSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { existsSync, mkdtempSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
3
4
|
import { join } from 'node:path';
|
|
5
|
+
import { looksLikeWorkspaceRoot } from "./layout.js";
|
|
4
6
|
// All feature members that exist in the ecosystem. The workspace manifest lists
|
|
5
7
|
// ALL of them (npm tolerates absent dirs), so a partial checkout still installs.
|
|
6
8
|
// But --tooling CLONES only app+core+requested — we do NOT force-clone all.
|
|
@@ -11,35 +13,104 @@ const ALWAYS_CLONE = ['app', 'core'];
|
|
|
11
13
|
// Listed in the manifest workspaces array (everything that could exist).
|
|
12
14
|
const ALL_MEMBERS = ['app', 'core', 'package-scripts', ...ALL_FEATURES];
|
|
13
15
|
/**
|
|
14
|
-
* Write a workspace-root package.json + .npmrc
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* Write (or merge into) a workspace-root package.json + .npmrc in `dir`.
|
|
17
|
+
*
|
|
18
|
+
* When `dir/package.json` already exists (e.g. provided by the workspace clone),
|
|
19
|
+
* we preserve its fields and only enforce the two things bootstrap owns:
|
|
20
|
+
* the complete `workspaces` list (so later --with clones need no manifest edit)
|
|
21
|
+
* and the `postinstall` script. All other fields — devDependencies, engines,
|
|
22
|
+
* volta, extra scripts, etc. — survive as-is.
|
|
23
|
+
*
|
|
24
|
+
* When no package.json exists yet (workspace clone was skipped), the full
|
|
25
|
+
* generated defaults are written, matching the previous behaviour.
|
|
26
|
+
*
|
|
27
|
+
* The workspaces array ALWAYS lists every possible member — npm ignores entries
|
|
28
|
+
* whose dirs are absent, so a partial checkout installs fine.
|
|
29
|
+
*
|
|
30
|
+
* .npmrc is written only when one does not already exist, for the same reason.
|
|
18
31
|
*/
|
|
19
32
|
export function writeWorkspaceManifest(dir) {
|
|
33
|
+
const pkgPath = join(dir, 'package.json');
|
|
34
|
+
let existing = {};
|
|
35
|
+
if (existsSync(pkgPath)) {
|
|
36
|
+
try {
|
|
37
|
+
existing = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// Unparseable existing file — start from defaults
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const existingScripts = typeof existing.scripts === 'object' && existing.scripts !== null
|
|
44
|
+
? existing.scripts
|
|
45
|
+
: {};
|
|
20
46
|
const pkg = {
|
|
21
47
|
name: '@tinycld/workspace',
|
|
22
48
|
version: '0.0.0',
|
|
23
49
|
private: true,
|
|
24
50
|
type: 'module',
|
|
51
|
+
...existing,
|
|
52
|
+
// Always enforce the canonical workspaces list and postinstall script.
|
|
25
53
|
workspaces: [...ALL_MEMBERS],
|
|
26
54
|
scripts: {
|
|
55
|
+
...existingScripts,
|
|
27
56
|
postinstall: 'cd app && npm run packages:generate && npm run assets:copy-pdfjs',
|
|
28
57
|
},
|
|
29
58
|
};
|
|
30
|
-
writeFileSync(
|
|
31
|
-
|
|
59
|
+
writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 4)}\n`);
|
|
60
|
+
const npmrcPath = join(dir, '.npmrc');
|
|
61
|
+
if (!existsSync(npmrcPath)) {
|
|
62
|
+
writeFileSync(npmrcPath, 'legacy-peer-deps=true\n');
|
|
63
|
+
}
|
|
32
64
|
}
|
|
33
65
|
function realClone(url, dest) {
|
|
34
66
|
const r = spawnSync('git', ['clone', '--depth', '1', url, dest], { stdio: 'inherit' });
|
|
35
67
|
return r.status === 0;
|
|
36
68
|
}
|
|
37
69
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
70
|
+
* Clone the workspace meta-repo into `root`, tolerating a non-empty target.
|
|
71
|
+
*
|
|
72
|
+
* A plain `git clone <url> <root>` fails when `root` already contains files
|
|
73
|
+
* (e.g. the link-package flow pre-creates a `<slug>/` subdir there). We
|
|
74
|
+
* clone into a fresh sibling temp dir, then move each top-level entry into
|
|
75
|
+
* `root`, skipping any that already exist. The `.git` dir is moved too unless
|
|
76
|
+
* `root/.git` already exists.
|
|
77
|
+
*
|
|
78
|
+
* The `cloneFn` primitive is the same injected-or-real clone used for app/core —
|
|
79
|
+
* tests inject a stub that records URLs but does not create files, so the
|
|
80
|
+
* move logic will simply move nothing from an empty temp dir (which is fine
|
|
81
|
+
* for unit tests). Real runs move the full repo contents.
|
|
82
|
+
*/
|
|
83
|
+
function cloneWorkspaceIntoRoot(url, root, cloneFn) {
|
|
84
|
+
const tempDir = mkdtempSync(join(tmpdir(), 'tinycld-workspace-'));
|
|
85
|
+
try {
|
|
86
|
+
if (!cloneFn(url, tempDir))
|
|
87
|
+
return false;
|
|
88
|
+
const rootHasGit = existsSync(join(root, '.git'));
|
|
89
|
+
for (const entry of readdirSync(tempDir)) {
|
|
90
|
+
// Skip .git if root already has one
|
|
91
|
+
if (entry === '.git' && rootHasGit)
|
|
92
|
+
continue;
|
|
93
|
+
const src = join(tempDir, entry);
|
|
94
|
+
const dest = join(root, entry);
|
|
95
|
+
// Never overwrite an entry that already exists in root
|
|
96
|
+
if (existsSync(dest))
|
|
97
|
+
continue;
|
|
98
|
+
renameSync(src, dest);
|
|
99
|
+
}
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Assemble a workspace skeleton at opts.root: if root is not yet a workspace,
|
|
108
|
+
* clone the workspace meta-repo into it first (self-init), then write the full
|
|
109
|
+
* manifest, then clone ONLY app + core + the explicitly-requested feature
|
|
110
|
+
* members (skipping any already present — e.g. a CI-checked-out member).
|
|
111
|
+
* Unknown member names throw. Returns the members that ended up present. Does
|
|
112
|
+
* NOT run npm install (the caller / CI controls that, since it may want a
|
|
113
|
+
* clean `npm ci`).
|
|
43
114
|
*/
|
|
44
115
|
export function bootstrapTooling(opts) {
|
|
45
116
|
const requested = opts.members ?? [];
|
|
@@ -49,9 +120,21 @@ export function bootstrapTooling(opts) {
|
|
|
49
120
|
}
|
|
50
121
|
const repoBase = opts.repoBase ?? 'git@github.com:tinycld';
|
|
51
122
|
const clone = opts.clone ?? realClone;
|
|
123
|
+
const present = [];
|
|
124
|
+
// Self-init: clone the workspace meta-repo into root if it isn't already
|
|
125
|
+
// a workspace root. This provides package-scripts/, tinycld.packages.ts,
|
|
126
|
+
// tests/, .node-version, .go-version, .npmrc, and the canonical root
|
|
127
|
+
// package.json before anything else runs.
|
|
128
|
+
if (!looksLikeWorkspaceRoot(opts.root)) {
|
|
129
|
+
if (cloneWorkspaceIntoRoot(`${repoBase}/workspace.git`, opts.root, clone)) {
|
|
130
|
+
present.push('workspace');
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Merge the canonical workspaces list + postinstall into any existing
|
|
134
|
+
// package.json (provided by the workspace clone), or write defaults when
|
|
135
|
+
// no file exists yet (workspace clone was skipped or failed).
|
|
52
136
|
writeWorkspaceManifest(opts.root);
|
|
53
137
|
const toClone = Array.from(new Set([...ALWAYS_CLONE, ...requested]));
|
|
54
|
-
const present = [];
|
|
55
138
|
for (const m of toClone) {
|
|
56
139
|
const dest = join(opts.root, m);
|
|
57
140
|
if (existsSync(join(dest, '.git')) || existsSync(join(dest, 'package.json'))) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap-tooling.js","sourceRoot":"","sources":["../src/bootstrap-tooling.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"bootstrap-tooling.js","sourceRoot":"","sources":["../src/bootstrap-tooling.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { realpathSync } from 'node:fs';
|
|
3
|
-
import { dirname, relative } from 'node:path';
|
|
3
|
+
import { dirname, join, relative } from 'node:path';
|
|
4
4
|
import { pathToFileURL } from 'node:url';
|
|
5
5
|
import { intro, outro } from '@clack/prompts';
|
|
6
6
|
import pc from 'picocolors';
|
|
@@ -12,7 +12,14 @@ import { offerLinkPackage } from "./link-package.js";
|
|
|
12
12
|
import { runPrompts } from "./prompts.js";
|
|
13
13
|
export function runToolingMode(opts) {
|
|
14
14
|
const root = opts.root ?? process.cwd();
|
|
15
|
-
|
|
15
|
+
// Honor TINYCLD_REPO_BASE (CI sets it to an HTTPS base since runners have no
|
|
16
|
+
// SSH key). Listed first so an explicit opts.repoBase still wins via spread;
|
|
17
|
+
// when neither is set, bootstrapTooling falls back to its SSH default.
|
|
18
|
+
const present = bootstrapTooling({
|
|
19
|
+
repoBase: process.env.TINYCLD_REPO_BASE,
|
|
20
|
+
...opts,
|
|
21
|
+
root,
|
|
22
|
+
});
|
|
16
23
|
// Mandatory members must clone — a missing app/core means a broken workspace.
|
|
17
24
|
for (const required of ['app', 'core']) {
|
|
18
25
|
if (!present.includes(required)) {
|
|
@@ -44,31 +51,33 @@ async function main() {
|
|
|
44
51
|
}
|
|
45
52
|
const answers = await runPrompts(args);
|
|
46
53
|
copyTemplate(resolveTemplatesRoot(import.meta.url), answers);
|
|
54
|
+
// The package lives at `<workspaceDir>/<slug>`, so its parent is the
|
|
55
|
+
// workspace dir in both attach (cwd) and bootstrap (wrapper) modes.
|
|
47
56
|
const linked = await offerLinkPackage({
|
|
48
|
-
|
|
49
|
-
|
|
57
|
+
slug: answers.slug,
|
|
58
|
+
workspaceDir: dirname(answers.targetDir),
|
|
50
59
|
mode: resolveLinkMode(args),
|
|
51
60
|
});
|
|
52
61
|
const relTarget = relative(process.cwd(), answers.targetDir) || answers.targetDir;
|
|
53
62
|
outro(pc.green(`Scaffolded ${pc.bold(answers.slug)} at ${pc.bold(relTarget)}`));
|
|
54
63
|
// Re-derive the layout from the resolved target so the next-steps output
|
|
55
64
|
// matches whatever path the user actually ended up at (default detection,
|
|
56
|
-
// explicit --target, or interactive override).
|
|
57
|
-
//
|
|
65
|
+
// explicit --target, or interactive override). It decides whether to print
|
|
66
|
+
// the bootstrap "self-contained workspace" note.
|
|
58
67
|
const layout = detectLayoutFromTarget(answers.targetDir, answers.slug);
|
|
59
68
|
printNextSteps({ slug: answers.slug, relTarget, linked, layout });
|
|
60
69
|
}
|
|
61
70
|
function detectLayoutFromTarget(targetDir, slug) {
|
|
62
|
-
// If cwd
|
|
63
|
-
//
|
|
64
|
-
//
|
|
71
|
+
// If cwd is itself a workspace root and target is a direct child of it,
|
|
72
|
+
// we're in attach mode. Otherwise the scaffolder created a wrapper under
|
|
73
|
+
// cwd and the workspace meta-repo gets cloned inside it (bootstrap mode).
|
|
65
74
|
const detected = detectLayout(slug);
|
|
66
75
|
if (detected.mode === 'attach' && targetDir === detected.targetDir)
|
|
67
76
|
return 'attach';
|
|
68
77
|
if (detected.mode === 'bootstrap' && targetDir === detected.targetDir)
|
|
69
78
|
return 'bootstrap';
|
|
70
79
|
// User passed an explicit --target. Infer from the on-disk shape: if the
|
|
71
|
-
// parent of targetDir
|
|
80
|
+
// parent of targetDir is itself a workspace root, treat as attach.
|
|
72
81
|
const parent = dirname(targetDir);
|
|
73
82
|
const looksAttached = detectLayout(slug, parent).mode === 'attach';
|
|
74
83
|
return looksAttached ? 'attach' : 'bootstrap';
|
|
@@ -85,11 +94,15 @@ function resolveLinkMode(args) {
|
|
|
85
94
|
function printNextSteps({ slug, relTarget, linked, layout }) {
|
|
86
95
|
const lines = ['', pc.bold('Next steps:'), ''];
|
|
87
96
|
let step = 1;
|
|
97
|
+
// The workspace root, relative to cwd. In bootstrap mode the package sits at
|
|
98
|
+
// `<wrapper>/<slug>`, so the wrapper (`dirname(relTarget)`) is the workspace
|
|
99
|
+
// root. In attach mode cwd already IS the workspace root, so it's `.`.
|
|
100
|
+
const wsRoot = dirname(relTarget) || '.';
|
|
88
101
|
if (layout === 'bootstrap') {
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
// got a self-contained workspace.
|
|
92
|
-
lines.push(pc.dim(` Scaffolded a self-contained workspace
|
|
102
|
+
// The meta-repo was cloned into the wrapper, so the wrapper itself is the
|
|
103
|
+
// workspace root and the new package is a member directory inside it.
|
|
104
|
+
// New users may not realize they just got a self-contained workspace.
|
|
105
|
+
lines.push(pc.dim(` Scaffolded a self-contained tinycld workspace.\n The workspace root is ./${wsRoot}/ and your package is ./${relTarget}/.\n The app member (Expo + PocketBase) is ./${wsRoot}/app/.\n`));
|
|
93
106
|
}
|
|
94
107
|
lines.push(` ${pc.dim(`# ${step++}. Initialize git and push to GitHub`)}`);
|
|
95
108
|
lines.push(` cd ${relTarget}`);
|
|
@@ -99,18 +112,24 @@ function printNextSteps({ slug, relTarget, linked, layout }) {
|
|
|
99
112
|
lines.push(` gh repo create tinycld/${slug} --public --source=. --push`);
|
|
100
113
|
lines.push('');
|
|
101
114
|
if (!linked) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
115
|
+
// Linking is now a workspace-root `npm install`: the package dir already
|
|
116
|
+
// exists; add it to the root package.json `workspaces` if it isn't a
|
|
117
|
+
// member yet, then install — npm symlinks it and the postinstall runs
|
|
118
|
+
// the generator.
|
|
119
|
+
lines.push(` ${pc.dim(`# ${step++}. Link into the workspace (add as a member, then install)`)}`);
|
|
120
|
+
if (wsRoot !== '.')
|
|
121
|
+
lines.push(` cd ${wsRoot}`);
|
|
122
|
+
lines.push(` # ensure "${slug}" is in this package.json's "workspaces" array, then:`);
|
|
123
|
+
lines.push(' npm install');
|
|
105
124
|
lines.push('');
|
|
106
125
|
}
|
|
107
|
-
lines.push(` ${pc.dim(`# ${step++}. Verify (biome + tsc
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
lines.push(' npm run checks');
|
|
126
|
+
lines.push(` ${pc.dim(`# ${step++}. Verify the package (biome + tsc, scoped to this member)`)}`);
|
|
127
|
+
lines.push(` cd ${join(wsRoot, slug)}`);
|
|
128
|
+
lines.push(' npx tinycld-pkg check');
|
|
111
129
|
lines.push('');
|
|
112
130
|
lines.push(` ${pc.dim(`# ${step++}. Run the app (Expo + PocketBase, single-port dev proxy)`)}`);
|
|
113
|
-
lines.push(
|
|
131
|
+
lines.push(` cd ${join(wsRoot, 'app')}`);
|
|
132
|
+
lines.push(' npm run dev');
|
|
114
133
|
lines.push('');
|
|
115
134
|
console.log(lines.join('\n'));
|
|
116
135
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/layout.js
CHANGED
|
@@ -1,37 +1,24 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { join, resolve } from 'node:path';
|
|
3
|
-
const APP_DIR_NAME = 'tinycld';
|
|
4
3
|
export function detectLayout(slug, cwd = process.cwd()) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return {
|
|
8
|
-
mode: 'attach',
|
|
9
|
-
targetDir: resolve(cwd, slug),
|
|
10
|
-
appDir: candidateApp,
|
|
11
|
-
};
|
|
4
|
+
if (looksLikeWorkspaceRoot(cwd)) {
|
|
5
|
+
return { mode: 'attach', targetDir: resolve(cwd, slug), workspaceDir: cwd };
|
|
12
6
|
}
|
|
13
|
-
const wrapperDir = resolve(cwd,
|
|
7
|
+
const wrapperDir = resolve(cwd, `tinycld-${slug}`);
|
|
14
8
|
return {
|
|
15
9
|
mode: 'bootstrap',
|
|
16
10
|
targetDir: join(wrapperDir, slug),
|
|
17
|
-
|
|
11
|
+
workspaceDir: wrapperDir,
|
|
18
12
|
wrapperDir,
|
|
19
13
|
};
|
|
20
14
|
}
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
* declaring `name: "tinycld"`. The bare directory check would false-match any
|
|
24
|
-
* unrelated `tinycld` directory; the package.json check is fast (one read of
|
|
25
|
-
* a file we'd be reading anyway) and unambiguous now that the app shell's
|
|
26
|
-
* package.json `name` field has been renamed from "@tinycld/app" to "tinycld".
|
|
27
|
-
*/
|
|
28
|
-
export function looksLikeAppShell(dir) {
|
|
15
|
+
/** A directory is a workspace root when its package.json name is "@tinycld/workspace". */
|
|
16
|
+
export function looksLikeWorkspaceRoot(dir) {
|
|
29
17
|
const pkgPath = join(dir, 'package.json');
|
|
30
18
|
if (!existsSync(pkgPath))
|
|
31
19
|
return false;
|
|
32
20
|
try {
|
|
33
|
-
|
|
34
|
-
return pkg?.name === 'tinycld';
|
|
21
|
+
return JSON.parse(readFileSync(pkgPath, 'utf-8'))?.name === '@tinycld/workspace';
|
|
35
22
|
}
|
|
36
23
|
catch {
|
|
37
24
|
return false;
|
package/dist/layout.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAgBzC,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IAClE,IAAI,sBAAsB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,YAAY,EAAE,GAAG,EAAE,CAAA;IAC/E,CAAC;IACD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,WAAW,IAAI,EAAE,CAAC,CAAA;IAClD,OAAO;QACH,IAAI,EAAE,WAAW;QACjB,SAAS,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC;QACjC,YAAY,EAAE,UAAU;QACxB,UAAU;KACb,CAAA;AACL,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,sBAAsB,CAAC,GAAW;IAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;IACzC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IACtC,IAAI,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,IAAI,KAAK,oBAAoB,CAAA;IACpF,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAA;IAChB,CAAC;AACL,CAAC"}
|
package/dist/link-package.js
CHANGED
|
@@ -1,85 +1,100 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process';
|
|
2
|
-
import { existsSync } from 'node:fs';
|
|
3
|
-
import {
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
4
|
import { confirm, isCancel, log, spinner } from '@clack/prompts';
|
|
5
5
|
import pc from 'picocolors';
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
import { bootstrapTooling } from "./bootstrap-tooling.js";
|
|
7
|
+
import { looksLikeWorkspaceRoot } from "./layout.js";
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
* Add `slug` to `<workspaceDir>/package.json` `workspaces[]` if it isn't already
|
|
10
|
+
* there. Idempotent, and a no-op when there's no package.json yet.
|
|
11
|
+
*/
|
|
12
|
+
export function ensureMember(workspaceDir, slug) {
|
|
13
|
+
const pkgPath = join(workspaceDir, 'package.json');
|
|
14
|
+
if (!existsSync(pkgPath))
|
|
15
|
+
return;
|
|
16
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
17
|
+
pkg.workspaces = Array.isArray(pkg.workspaces) ? pkg.workspaces : [];
|
|
18
|
+
if (!pkg.workspaces.includes(slug)) {
|
|
19
|
+
pkg.workspaces.push(slug);
|
|
20
|
+
writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 4)}\n`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Offer to link the freshly-scaffolded package into the TinyCld workspace.
|
|
25
|
+
*
|
|
26
|
+
* "Linking" in the workspace layout means: make the package a workspace member
|
|
27
|
+
* (its dir name appears in the root `package.json` `workspaces[]`) and run
|
|
28
|
+
* `npm install` at the workspace root — npm creates the `node_modules/@tinycld/*`
|
|
29
|
+
* symlink and the root `postinstall` runs the generator.
|
|
30
|
+
*
|
|
31
|
+
* Two shapes, distinguished by whether `workspaceDir` is already a workspace root:
|
|
32
|
+
* - attach: `workspaceDir` already holds the workspace meta-repo (its
|
|
33
|
+
* package.json name is `@tinycld/workspace`). No assembly — just ensure the
|
|
34
|
+
* member and install. The existing root package.json is left untouched.
|
|
35
|
+
* - bootstrap: `workspaceDir` is a fresh wrapper that only contains the
|
|
36
|
+
* scaffolded `<slug>/` so far. Assemble the workspace *around* it — write the
|
|
37
|
+
* workspace manifest and clone app + core via `bootstrapTooling` — then
|
|
38
|
+
* ensure the new member and install. The `postinstall` (`cd app && …`) only
|
|
39
|
+
* succeeds once `app/` exists, which is why we assemble before installing.
|
|
13
40
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* server's `replace tinycld.org/core => ../../tinycld/packages/@tinycld/core/server`
|
|
19
|
-
* directive both resolve into the bundled core inside the app shell.
|
|
41
|
+
* Returns true if the user chose to link (even if a subprocess failed — the
|
|
42
|
+
* error is already logged, and we don't want to follow up with manual steps
|
|
43
|
+
* when the user already expressed intent). Returns false only when linking was
|
|
44
|
+
* declined or skipped.
|
|
20
45
|
*/
|
|
21
|
-
export async function offerLinkPackage({
|
|
46
|
+
export async function offerLinkPackage({ slug, workspaceDir, mode, assemble = realAssemble, install = realInstall, }) {
|
|
22
47
|
if (mode === 'skip')
|
|
23
48
|
return false;
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
const appExists = existsSync(appDir);
|
|
49
|
+
// A wrapper that isn't yet a workspace root needs app + core assembled in.
|
|
50
|
+
const needsClone = !looksLikeWorkspaceRoot(workspaceDir);
|
|
27
51
|
if (mode === 'prompt') {
|
|
28
|
-
const
|
|
29
|
-
? `
|
|
30
|
-
: `
|
|
31
|
-
const answer = await confirm({ message
|
|
52
|
+
const message = needsClone
|
|
53
|
+
? `Clone the tinycld workspace (app + core) and link ${pc.bold(slug)} now?`
|
|
54
|
+
: `Link ${pc.bold(slug)} into the workspace now?`;
|
|
55
|
+
const answer = await confirm({ message, initialValue: true });
|
|
32
56
|
if (isCancel(answer) || answer !== true)
|
|
33
57
|
return false;
|
|
34
58
|
}
|
|
35
|
-
if (
|
|
36
|
-
|
|
59
|
+
if (needsClone) {
|
|
60
|
+
const s = spinner();
|
|
61
|
+
s.start('Assembling the tinycld workspace (app + core)');
|
|
62
|
+
try {
|
|
63
|
+
assemble(workspaceDir);
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
s.stop(pc.red('Workspace assembly failed'), 1);
|
|
67
|
+
log.error(err instanceof Error ? err.message : String(err));
|
|
37
68
|
return true;
|
|
69
|
+
}
|
|
70
|
+
s.stop('Assembled the tinycld workspace');
|
|
38
71
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const inst = spawnSync('npm', ['install'], { cwd: appDir, stdio: 'pipe', encoding: 'utf8' });
|
|
45
|
-
if (inst.status !== 0) {
|
|
46
|
-
install.stop(pc.red('npm install failed'), 1);
|
|
47
|
-
log.error(inst.stderr.trim() || 'npm install exited non-zero');
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
install.stop(`Installed ${APP_DIR_NAME} dependencies`);
|
|
51
|
-
// packages:link in tinycld takes a sibling-directory locator and reads
|
|
52
|
-
// the package name from the sibling's package.json. Pass a path relative
|
|
53
|
-
// to the app shell so the symlink target stays portable.
|
|
54
|
-
const link = spinner();
|
|
55
|
-
link.start(`Linking ${packageName}`);
|
|
56
|
-
const locator = relative(appDir, targetDir) || targetDir;
|
|
57
|
-
const linkResult = spawnSync('npm', ['run', 'packages:link', locator], {
|
|
58
|
-
cwd: appDir,
|
|
59
|
-
stdio: 'pipe',
|
|
60
|
-
encoding: 'utf8',
|
|
61
|
-
});
|
|
62
|
-
if (linkResult.status !== 0) {
|
|
63
|
-
link.stop(pc.red('Link failed'), 1);
|
|
64
|
-
log.error(linkResult.stderr.trim() || 'packages:link exited non-zero');
|
|
72
|
+
ensureMember(workspaceDir, slug);
|
|
73
|
+
const i = spinner();
|
|
74
|
+
i.start('Installing workspace (npm install)');
|
|
75
|
+
if (!install(workspaceDir)) {
|
|
76
|
+
i.stop(pc.red('npm install failed'), 1);
|
|
65
77
|
return true;
|
|
66
78
|
}
|
|
67
|
-
|
|
79
|
+
i.stop('Installed workspace');
|
|
80
|
+
log.success(`Linked ${pc.bold(slug)} into the workspace`);
|
|
68
81
|
return true;
|
|
69
82
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
83
|
+
/**
|
|
84
|
+
* Assemble the workspace skeleton at `dir`: write the workspace manifest and
|
|
85
|
+
* clone app + core (honoring `TINYCLD_REPO_BASE` for keyless/HTTPS envs).
|
|
86
|
+
* `bootstrapTooling` is synchronous and throws on failure (unknown member, etc.);
|
|
87
|
+
* `offerLinkPackage` wraps the call so the error surfaces in the spinner.
|
|
88
|
+
*/
|
|
89
|
+
function realAssemble(dir) {
|
|
90
|
+
bootstrapTooling({ root: dir, repoBase: process.env.TINYCLD_REPO_BASE });
|
|
91
|
+
}
|
|
92
|
+
function realInstall(cwd) {
|
|
93
|
+
const r = spawnSync('npm', ['install'], { cwd, stdio: 'pipe', encoding: 'utf8' });
|
|
94
|
+
if (r.status !== 0) {
|
|
95
|
+
log.error(r.stderr?.trim() || 'npm install exited non-zero');
|
|
80
96
|
return false;
|
|
81
97
|
}
|
|
82
|
-
s.stop(`Cloned ${dest}`);
|
|
83
98
|
return true;
|
|
84
99
|
}
|
|
85
100
|
//# sourceMappingURL=link-package.js.map
|
package/dist/link-package.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-package.js","sourceRoot":"","sources":["../src/link-package.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"link-package.js","sourceRoot":"","sources":["../src/link-package.ts"],"names":[],"mappings":"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"}
|
package/dist/prompts.js
CHANGED
|
@@ -165,9 +165,9 @@ async function resolveTarget(fromArgv, slug, skipPrompts) {
|
|
|
165
165
|
return abs;
|
|
166
166
|
}
|
|
167
167
|
// No --target: pick a sensible default based on the cwd's existing layout.
|
|
168
|
-
// If cwd
|
|
169
|
-
//
|
|
170
|
-
//
|
|
168
|
+
// If cwd is itself a workspace root, attach the new package as a direct
|
|
169
|
+
// child `<cwd>/<slug>`. Otherwise bootstrap a wrapper workspace under
|
|
170
|
+
// `<cwd>/tinycld-<slug>/` and place the package inside it.
|
|
171
171
|
const layout = detectLayout(slug);
|
|
172
172
|
const defaultAbs = layout.targetDir;
|
|
173
173
|
const defaultDisplay = `./${relative(process.cwd(), defaultAbs) || slug}`;
|
package/dist/prompts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -17,7 +17,13 @@
|
|
|
17
17
|
"./components/*": "./tinycld/{{PKG_SLUG}}/components/*.tsx"
|
|
18
18
|
},
|
|
19
19
|
"scripts": {
|
|
20
|
-
"typecheck": "
|
|
20
|
+
"typecheck": "tinycld-pkg typecheck",
|
|
21
|
+
"test": "tinycld-pkg test",
|
|
22
|
+
"test:e2e": "tinycld-pkg test:e2e",
|
|
23
|
+
"check": "tinycld-pkg check"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@tinycld/package-scripts": "*"
|
|
21
27
|
},
|
|
22
28
|
"peerDependencies": {
|
|
23
29
|
"react": ">=19",
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import { defineConfig } from '@playwright/test'
|
|
3
|
+
import appConfig from '../app/playwright.config'
|
|
4
|
+
|
|
5
|
+
// Package-scoped Playwright: inherit the app shell's webServer + browser config,
|
|
6
|
+
// then point testDir at THIS package's tests/e2e through the app shell's
|
|
7
|
+
// node_modules symlink. Routing via node_modules (not this repo's real path)
|
|
8
|
+
// keeps node resolution walking up into the app shell's install, so
|
|
9
|
+
// @playwright/test and other deps resolve there — not from a (nonexistent)
|
|
10
|
+
// local node_modules.
|
|
11
|
+
// The @tinycld/{{PKG_SLUG}} symlink lives in the workspace-root node_modules (deps
|
|
12
|
+
// hoist there in this layout). Routing testDir through it keeps node resolution
|
|
13
|
+
// walking up into the install where @playwright/test lives.
|
|
14
|
+
const WS_ROOT = path.resolve(import.meta.dirname, '..')
|
|
15
|
+
const TEST_DIR = path.join(WS_ROOT, 'node_modules', '@tinycld', '{{PKG_SLUG}}', 'tests', 'e2e')
|
|
16
|
+
|
|
17
|
+
export default defineConfig({
|
|
18
|
+
...appConfig,
|
|
19
|
+
testDir: TEST_DIR,
|
|
20
|
+
})
|
|
@@ -3,8 +3,8 @@ module {{GO_MODULE}}
|
|
|
3
3
|
go 1.25.0
|
|
4
4
|
|
|
5
5
|
require (
|
|
6
|
-
github.com/pocketbase/pocketbase v0.
|
|
6
|
+
github.com/pocketbase/pocketbase v0.37.5
|
|
7
7
|
tinycld.org/core v0.0.0
|
|
8
8
|
)
|
|
9
9
|
|
|
10
|
-
replace tinycld.org/core => ../../
|
|
10
|
+
replace tinycld.org/core => ../../core/server
|
|
@@ -13,7 +13,12 @@
|
|
|
13
13
|
"./hooks/*": "./tinycld/{{PKG_SLUG}}/hooks/*.ts"
|
|
14
14
|
},
|
|
15
15
|
"scripts": {
|
|
16
|
-
"typecheck": "
|
|
16
|
+
"typecheck": "tinycld-pkg typecheck",
|
|
17
|
+
"test": "tinycld-pkg test",
|
|
18
|
+
"check": "tinycld-pkg check"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@tinycld/package-scripts": "*"
|
|
17
22
|
},
|
|
18
23
|
"peerDependencies": {
|
|
19
24
|
"react": ">=19",
|
|
@@ -7,53 +7,77 @@ on:
|
|
|
7
7
|
branches: [main]
|
|
8
8
|
|
|
9
9
|
env:
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
PACKAGE: {{PKG_SLUG}}
|
|
11
|
+
TEST_USER_LOGIN: user@tinycld.org
|
|
12
|
+
TEST_USER_PW: TestUser1234!
|
|
13
|
+
ADMIN_USER_LOGIN: admin@tinycld.org
|
|
14
|
+
ADMIN_USER_PW: AdminPass1234!
|
|
12
15
|
|
|
13
16
|
jobs:
|
|
14
|
-
|
|
15
|
-
name:
|
|
17
|
+
check:
|
|
18
|
+
name: Typecheck & Unit
|
|
16
19
|
runs-on: ubuntu-latest
|
|
17
20
|
steps:
|
|
21
|
+
# 1. The workspace meta-repo becomes the job root.
|
|
18
22
|
- uses: actions/checkout@v5
|
|
19
23
|
with:
|
|
20
|
-
|
|
24
|
+
repository: tinycld/workspace
|
|
25
|
+
ref: main
|
|
26
|
+
path: ws
|
|
27
|
+
# 2. This PR's code, checked out into the member slot.
|
|
21
28
|
- uses: actions/checkout@v5
|
|
22
29
|
with:
|
|
23
|
-
|
|
24
|
-
ref: ${{ env.APP_REF }}
|
|
25
|
-
path: tinycld
|
|
30
|
+
path: ws/${{ env.PACKAGE }}
|
|
26
31
|
- uses: actions/setup-node@v5
|
|
27
32
|
with:
|
|
28
|
-
node-version-file:
|
|
33
|
+
node-version-file: ws/.node-version
|
|
29
34
|
cache: npm
|
|
30
|
-
cache-dependency-path:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
- name:
|
|
41
|
-
working-directory:
|
|
42
|
-
run: npm
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
run: npm run lint
|
|
47
|
-
|
|
48
|
-
# Typecheck runs from inside tinycld so module resolution sees the
|
|
49
|
-
# full app-shell tree (uniwind augments, expo types, etc) — running
|
|
50
|
-
# tsc standalone in the package directory misses those.
|
|
51
|
-
- name: Typecheck (full app shell, package included via link)
|
|
52
|
-
working-directory: tinycld
|
|
53
|
-
env:
|
|
54
|
-
NODE_OPTIONS: --preserve-symlinks
|
|
55
|
-
run: npm run typecheck
|
|
35
|
+
cache-dependency-path: ws/package-lock.json
|
|
36
|
+
- uses: actions/setup-go@v6
|
|
37
|
+
with:
|
|
38
|
+
go-version-file: ws/.go-version
|
|
39
|
+
# 3. Clone app + core (the PR's PACKAGE is already checked out into its
|
|
40
|
+
# slot; bootstrap --tooling skips dirs that already exist). A sibling
|
|
41
|
+
# only needs app + core + itself to typecheck + unit-test.
|
|
42
|
+
- name: Assemble workspace (app + core)
|
|
43
|
+
working-directory: ws
|
|
44
|
+
run: TINYCLD_REPO_BASE=https://github.com/tinycld npx @tinycld/bootstrap@latest --tooling
|
|
45
|
+
- name: Install (workspace root)
|
|
46
|
+
working-directory: ws
|
|
47
|
+
run: npm install
|
|
48
|
+
- name: Typecheck + unit
|
|
49
|
+
working-directory: ws/${{ env.PACKAGE }}
|
|
50
|
+
run: npx tinycld-pkg check
|
|
56
51
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
e2e:
|
|
53
|
+
name: E2E
|
|
54
|
+
runs-on: ubuntu-latest
|
|
55
|
+
steps:
|
|
56
|
+
- uses: actions/checkout@v5
|
|
57
|
+
with:
|
|
58
|
+
repository: tinycld/workspace
|
|
59
|
+
ref: main
|
|
60
|
+
path: ws
|
|
61
|
+
- uses: actions/checkout@v5
|
|
62
|
+
with:
|
|
63
|
+
path: ws/${{ env.PACKAGE }}
|
|
64
|
+
- uses: actions/setup-node@v5
|
|
65
|
+
with:
|
|
66
|
+
node-version-file: ws/.node-version
|
|
67
|
+
cache: npm
|
|
68
|
+
cache-dependency-path: ws/package-lock.json
|
|
69
|
+
- uses: actions/setup-go@v6
|
|
70
|
+
with:
|
|
71
|
+
go-version-file: ws/.go-version
|
|
72
|
+
- name: Assemble workspace (app + core)
|
|
73
|
+
working-directory: ws
|
|
74
|
+
run: TINYCLD_REPO_BASE=https://github.com/tinycld npx @tinycld/bootstrap@latest --tooling
|
|
75
|
+
- name: Install (workspace root)
|
|
76
|
+
working-directory: ws
|
|
77
|
+
run: npm install
|
|
78
|
+
- name: Install Playwright browsers
|
|
79
|
+
working-directory: ws/app
|
|
80
|
+
run: npx playwright install --with-deps chromium
|
|
81
|
+
- name: E2E
|
|
82
|
+
working-directory: ws/${{ env.PACKAGE }}
|
|
83
|
+
run: npx tinycld-pkg test:e2e
|
|
@@ -2,53 +2,64 @@
|
|
|
2
2
|
|
|
3
3
|
{{PKG_DESCRIPTION}}
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
A feature package for the [tinycld](https://tinycld.org/) ecosystem. It lives in
|
|
6
|
+
its own git repo and is developed as a **workspace member** alongside the app
|
|
7
|
+
shell (`app`), `@tinycld/core` (its own standalone repo, cloned as a sibling —
|
|
8
|
+
not bundled), and the other feature packages.
|
|
6
9
|
|
|
7
10
|
## Development
|
|
8
11
|
|
|
12
|
+
The package is one member of a tinycld workspace. To work on it you need a
|
|
13
|
+
workspace root containing at least `app`, `core`, and this package as siblings,
|
|
14
|
+
linked by a single `npm install` at the root.
|
|
15
|
+
|
|
9
16
|
```sh
|
|
10
|
-
#
|
|
11
|
-
cd ~/code/tinycld
|
|
12
|
-
git clone git@github.com:tinycld/tinycld.git
|
|
17
|
+
# In a fresh workspace directory, clone this package into a member slot…
|
|
13
18
|
git clone git@github.com:tinycld/{{PKG_SLUG}}.git
|
|
14
19
|
|
|
15
|
-
#
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
# …then pull in the rest of the workspace tooling (app + core + the root
|
|
21
|
+
# package.json / lockfile). bootstrap --tooling skips dirs that already exist.
|
|
22
|
+
npx @tinycld/bootstrap@latest --tooling
|
|
18
23
|
|
|
19
|
-
# Link
|
|
20
|
-
|
|
24
|
+
# Link every member with one install at the WORKSPACE ROOT (never inside a
|
|
25
|
+
# member — siblings have no node_modules of their own; deps hoist to the root).
|
|
26
|
+
npm install
|
|
21
27
|
|
|
22
|
-
# Run the full stack
|
|
23
|
-
|
|
28
|
+
# Run the full stack (Expo + PocketBase, single-port dev proxy) from the app.
|
|
29
|
+
cd app
|
|
30
|
+
npm run dev
|
|
24
31
|
```
|
|
25
32
|
|
|
26
|
-
##
|
|
33
|
+
## Checks
|
|
27
34
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
none of which a standalone invocation in this package can see. Biome's
|
|
32
|
-
config lives in `tinycld/biome.json` and applies to every linked package
|
|
33
|
-
(there is no `biome.json` in this repo).
|
|
35
|
+
All checks run **scoped to this member** through `tinycld-pkg`, which reuses the
|
|
36
|
+
app shell's biome config, tsconfig base, and vitest/playwright configs (so
|
|
37
|
+
`@tinycld/core/*`, uniwind augments, and PocketBase types all resolve):
|
|
34
38
|
|
|
35
39
|
```sh
|
|
36
|
-
cd
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
cd {{PKG_SLUG}}
|
|
41
|
+
npx tinycld-pkg check # biome + typecheck
|
|
42
|
+
npx tinycld-pkg test # vitest unit tests
|
|
43
|
+
npx tinycld-pkg test:e2e # playwright e2e specs (full preset only — packages with screens)
|
|
40
44
|
```
|
|
41
45
|
|
|
46
|
+
There is no `biome.json` in this repo — biome lives only in the app shell and
|
|
47
|
+
`tinycld-pkg` points it at this member's source.
|
|
48
|
+
|
|
42
49
|
## CI
|
|
43
50
|
|
|
44
|
-
`.github/workflows/ci.yml` runs
|
|
45
|
-
`main` and every PR. It
|
|
46
|
-
|
|
47
|
-
|
|
51
|
+
`.github/workflows/ci.yml` runs typecheck, unit tests, and e2e on every push to
|
|
52
|
+
`main` and every PR. It checks out `tinycld/workspace` as the job root, drops
|
|
53
|
+
this PR's code into its member slot, assembles `app` + `core` via
|
|
54
|
+
`@tinycld/bootstrap --tooling`, installs at the workspace root, and runs
|
|
55
|
+
`tinycld-pkg check` / `tinycld-pkg test:e2e` — exactly what a developer runs
|
|
56
|
+
locally.
|
|
48
57
|
|
|
49
58
|
## Package anatomy
|
|
50
59
|
|
|
51
60
|
- `manifest.ts` — the single source of truth for this package's capabilities
|
|
52
|
-
- `package.json` — name, exports map, peer deps
|
|
53
|
-
- `tsconfig.json` —
|
|
54
|
-
- `
|
|
61
|
+
- `package.json` — name, exports map, `tinycld-pkg` scripts, peer deps
|
|
62
|
+
- `tsconfig.json` — extends the app shell's package tsconfig base
|
|
63
|
+
- `vitest.config.ts` (and `playwright.config.ts` — full preset only) — thin configs spreading the app's
|
|
64
|
+
- `tinycld/{{PKG_SLUG}}/` — the package's TypeScript surface (screens, collections, …)
|
|
65
|
+
- `tests/` — vitest unit tests (and Playwright e2e specs — full preset only)
|
|
@@ -1,22 +1,13 @@
|
|
|
1
1
|
{
|
|
2
|
-
"extends": "../
|
|
2
|
+
"extends": "../app/tsconfig.package-base.json",
|
|
3
3
|
"compilerOptions": {
|
|
4
4
|
"baseUrl": ".",
|
|
5
|
-
"rootDir": "..",
|
|
6
5
|
"paths": {
|
|
7
6
|
"~/tinycld/{{PKG_SLUG}}/*": ["./tinycld/{{PKG_SLUG}}/*"],
|
|
8
|
-
"@tinycld/
|
|
9
|
-
"@tinycld/
|
|
10
|
-
|
|
11
|
-
},
|
|
12
|
-
"noEmit": true,
|
|
13
|
-
"preserveSymlinks": false
|
|
7
|
+
"@tinycld/core/*": ["../core/*"],
|
|
8
|
+
"@tinycld/app-generated/*": ["../app/lib/generated/*"]
|
|
9
|
+
}
|
|
14
10
|
},
|
|
15
|
-
"include": [
|
|
16
|
-
"**/*.ts",
|
|
17
|
-
"**/*.tsx",
|
|
18
|
-
"../tinycld/uniwind-types.d.ts",
|
|
19
|
-
"../tinycld/expo-env.d.ts"
|
|
20
|
-
],
|
|
11
|
+
"include": ["tinycld/**/*.ts", "tinycld/**/*.tsx", "../app/uniwind-types.d.ts"],
|
|
21
12
|
"exclude": ["node_modules", "server", "pb-migrations", "tests/**/*.spec.ts"]
|
|
22
13
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import { mergeConfig } from 'vitest/config'
|
|
3
|
+
import appConfig from '../app/vitest.config'
|
|
4
|
+
|
|
5
|
+
// Package-scoped vitest: inherit the app shell's canonical aliases (so
|
|
6
|
+
// @tinycld/core/* etc. resolve identically), then add this package's own
|
|
7
|
+
// `~/*` source alias and scope the run to this package's tests/.
|
|
8
|
+
export default mergeConfig(appConfig, {
|
|
9
|
+
resolve: {
|
|
10
|
+
alias: [{ find: /^~\/(.+)$/, replacement: path.resolve(__dirname, '$1') }],
|
|
11
|
+
},
|
|
12
|
+
test: {
|
|
13
|
+
root: __dirname,
|
|
14
|
+
include: ['tests/**/*.test.{ts,tsx}'],
|
|
15
|
+
},
|
|
16
|
+
})
|