@tinycld/bootstrap 2.4.3 → 2.4.4

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/validate.js CHANGED
@@ -3,6 +3,32 @@ const SLUG_RE = /^[a-z][a-z0-9-]*[a-z0-9]$/;
3
3
  const RESERVED_SLUGS = new Set(['core', 'main', 'test', 'tests', 'node_modules', 'packages']);
4
4
  const SHORTCUT_RE = /^[a-z]$/;
5
5
  const ICON_RE = /^[a-z][a-z0-9-]*$/;
6
+ // Free-text fields (name, description) are substituted VERBATIM into single-quoted
7
+ // TS strings, JSON, JSX text, and Go/Markdown comments in the generated scaffold.
8
+ // Quotes, backslashes, backticks, template-literal openers, and control chars
9
+ // (newlines/tabs) would break — or inject into — that output. Reject them so the
10
+ // user re-runs with a clean value; escaping correctly per-context is far more
11
+ // fragile than disallowing characters that have no business in a package name.
12
+ const UNSAFE_CHARS = ["'", '"', '`', '\\'];
13
+ function hasControlChar(value) {
14
+ for (let i = 0; i < value.length; i++) {
15
+ const code = value.charCodeAt(i);
16
+ if (code < 0x20 || code === 0x7f)
17
+ return true;
18
+ }
19
+ return false;
20
+ }
21
+ function validateFreeText(value) {
22
+ if (hasControlChar(value))
23
+ return 'must not contain newlines, tabs, or other control characters';
24
+ if (value.includes('${'))
25
+ return 'must not contain "${" (template-literal syntax)';
26
+ for (const ch of UNSAFE_CHARS) {
27
+ if (value.includes(ch))
28
+ return `must not contain the ${ch} character`;
29
+ }
30
+ return null;
31
+ }
6
32
  export function validateSlug(slug) {
7
33
  if (!slug || slug.length < 3)
8
34
  return 'Slug must be at least 3 characters';
@@ -20,6 +46,9 @@ export function validateName(name) {
20
46
  return 'Name is required';
21
47
  if (name.length > 60)
22
48
  return 'Name must be 60 characters or fewer';
49
+ const err = validateFreeText(name);
50
+ if (err)
51
+ return `Name ${err}`;
23
52
  return null;
24
53
  }
25
54
  export function validateDescription(desc) {
@@ -27,6 +56,9 @@ export function validateDescription(desc) {
27
56
  return 'Description is required';
28
57
  if (desc.length > 200)
29
58
  return 'Description must be 200 characters or fewer';
59
+ const err = validateFreeText(desc);
60
+ if (err)
61
+ return `Description ${err}`;
30
62
  return null;
31
63
  }
32
64
  export function validateIcon(icon) {
@@ -1 +1 @@
1
- {"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinycld/bootstrap",
3
- "version": "2.4.3",
3
+ "version": "2.4.4",
4
4
  "description": "Scaffolder for @tinycld feature packages",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,6 +1,6 @@
1
1
  import path from 'node:path'
2
2
  import { defineConfig } from '@playwright/test'
3
- import appConfig from '../app/playwright.config'
3
+ import appConfig from '@tinycld/core/playwright-config'
4
4
 
5
5
  // Package-scoped Playwright: inherit the app shell's webServer + browser config,
6
6
  // then point testDir at THIS package's tests/e2e through the app shell's
@@ -28,9 +28,10 @@ jobs:
28
28
  with:
29
29
  node-version: '24'
30
30
  # 3. Assemble the workspace root: writes package.json + tinycld.packages.ts
31
- # from bootstrap's embedded templates, clones app + core as siblings.
32
- # The PR's PACKAGE dir is already there and is skipped.
33
- - name: Assemble workspace (app + core)
31
+ # from bootstrap's embedded templates, clones the tinycld member (app
32
+ # shell + core + package-scripts) as a sibling. The PR's PACKAGE dir is
33
+ # already there and is skipped.
34
+ - name: Assemble workspace (tinycld + this package)
34
35
  working-directory: ws
35
36
  run: TINYCLD_REPO_BASE=https://github.com/tinycld npx @tinycld/bootstrap@latest --assemble-only
36
37
  # 4. Now switch to the version the assembled workspace pins (ws/.node-version
@@ -66,7 +67,7 @@ jobs:
66
67
  - uses: actions/setup-node@v5
67
68
  with:
68
69
  node-version: '24'
69
- - name: Assemble workspace (app + core)
70
+ - name: Assemble workspace (tinycld + this package)
70
71
  working-directory: ws
71
72
  run: TINYCLD_REPO_BASE=https://github.com/tinycld npx @tinycld/bootstrap@latest --assemble-only
72
73
  # Switch to the version the assembled workspace pins.
@@ -81,16 +82,16 @@ jobs:
81
82
  - name: Install (workspace root)
82
83
  working-directory: ws
83
84
  run: pnpm install --no-frozen-lockfile
84
- # Installs watchman so Metro's file watcher doesn't fall back to
85
- # polling — see tinycld/app#21 for the trace evidence and the
86
- # blank-page-after-reload flake it fixed.
85
+ # Installs the Playwright browser and pre-builds the web bundle. The
86
+ # composite action lives in the tinycld member, assembled at ws/tinycld.
87
87
  - name: Configure test env
88
- uses: tinycld/app/.github/actions/configure-test-env@main
89
- - name: Install Playwright browsers
90
- working-directory: ws/app
91
- run: pnpm exec playwright install --with-deps chromium
88
+ uses: ./ws/tinycld/.github/actions/configure-test-env
92
89
  - name: E2E
93
90
  working-directory: ws/${{ env.PACKAGE }}
91
+ env:
92
+ # The bundle was built by the action above; reuse it (the webServer
93
+ # still seeds + promotes + serves, just doesn't export a second time).
94
+ TINYCLD_E2E_SKIP_EXPORT: '1'
94
95
  run: pnpm exec tinycld-pkg test:e2e
95
96
  # Capture Playwright's per-failure artifacts (trace, screenshot,
96
97
  # video, error-context.md) so a CI failure can be diagnosed
@@ -1,6 +1,6 @@
1
1
  import path from 'node:path'
2
+ import appConfig from '@tinycld/core/vitest-config'
2
3
  import { mergeConfig } from 'vitest/config'
3
- import appConfig from '../app/vitest.config'
4
4
 
5
5
  // Package-scoped vitest: inherit the app shell's canonical aliases (so
6
6
  // @tinycld/core/* etc. resolve identically), then add this package's own
@@ -6,8 +6,8 @@ import { defineConfig } from 'vitest/config'
6
6
  // react-native/expo/sentry mocks that let the broader core suite run under
7
7
  // Node without the Metro/RN runtime.
8
8
  const ROOT = import.meta.dirname
9
- const CORE_DIR = path.join(ROOT, 'core')
10
- const APP_GENERATED = path.join(ROOT, 'app', 'lib', 'generated')
9
+ const CORE_DIR = path.join(ROOT, 'tinycld', 'core')
10
+ const APP_GENERATED = path.join(ROOT, 'tinycld', 'lib', 'generated')
11
11
 
12
12
  // Locate a hoisted dependency's dir. In this workspace layout deps hoist to
13
13
  // the workspace-root node_modules (all members declare framework deps as
@@ -62,7 +62,7 @@ export default defineConfig({
62
62
  replacement: `${CORE_DIR}/$1`,
63
63
  },
64
64
  // --- @tinycld/app-generated/* build-time contract (written to
65
- // app/lib/generated/ by the generator; Vitest doesn't read
65
+ // tinycld/lib/generated/ by the generator; Vitest doesn't read
66
66
  // tsconfig paths) ---
67
67
  {
68
68
  find: /^@tinycld\/app-generated\/(.+)$/,
@@ -102,10 +102,10 @@ export default defineConfig({
102
102
  environment: 'node',
103
103
  include: [
104
104
  'tests/**/*.test.{ts,tsx}',
105
- 'core/**/__tests__/**/*.test.{ts,tsx}',
106
- 'core/**/*.test.{ts,tsx}',
107
- 'app/scripts/**/__tests__/**/*.test.{ts,tsx}',
108
- 'package-scripts/tests/**/*.test.{ts,tsx}',
105
+ 'tinycld/core/**/__tests__/**/*.test.{ts,tsx}',
106
+ 'tinycld/core/**/*.test.{ts,tsx}',
107
+ 'tinycld/scripts/**/__tests__/**/*.test.{ts,tsx}',
108
+ 'tinycld/package-scripts/tests/**/*.test.{ts,tsx}',
109
109
  ],
110
110
  setupFiles: ['tests/unit-setup.ts'],
111
111
  },