@hearthlog/tooling 0.1.0 → 0.1.2

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/bin/hearthlog.mjs CHANGED
@@ -41,6 +41,15 @@ if (deployTools[command]) {
41
41
  process.exit(built === 0 ? (spawnSync(process.execPath, [tsx, source(deployTools[command]), ...rest], { stdio: 'inherit', env }).status ?? 1) : built);
42
42
  }
43
43
 
44
+ // The plan reads the site's generated files too: build them first (a no-op when they are current). `apply` does not,
45
+ // because `apply --skip-build` deploys the release already in place and must not rewrite it.
46
+ if (command === 'plan') {
47
+ const site = rest[rest.indexOf('--site') + 1];
48
+ const env = { ...process.env, ...(rest.includes('--site') && site ? { VITE_STOR_TENANT: site } : {}) };
49
+ const built = spawnSync(process.execPath, [tsx, source('generate/build-generated.ts'), '--quiet'], { stdio: 'inherit', env }).status ?? 1;
50
+ if (built !== 0) process.exit(built);
51
+ }
52
+
44
53
  const entry = {
45
54
  build: 'generate/build-generated.ts',
46
55
  init: 'init/init.ts',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hearthlog/tooling",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "license": "AGPL-3.0-only",
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "tsx": "^4.23.15",
31
- "@hearthlog/contracts": "0.1.0"
31
+ "@hearthlog/contracts": "0.1.2"
32
32
  },
33
33
  "bin": {
34
34
  "hearthlog": "./bin/hearthlog.mjs"
@@ -155,6 +155,7 @@ export function exportModule(modulesDirectory: string, name: string, out: string
155
155
  writeFileSync(packagePath, `${JSON.stringify(publishable, null, 2)}\n`);
156
156
  mkdirSync(join(out, ".github", "workflows"), { recursive: true });
157
157
  copyFileSync(join(TEMPLATE, "gitignore.tmpl"), join(out, ".gitignore"));
158
+ copyFileSync(join(TEMPLATE, "gitleaks.toml.tmpl"), join(out, ".gitleaks.toml"));
158
159
  // vitest's esbuild needs its install script; pnpm 10 asks for it by name.
159
160
  writeFileSync(join(out, "pnpm-workspace.yaml"), "onlyBuiltDependencies:\n - esbuild\n");
160
161
  copyFileSync(join(TEMPLATE, "ci.yml.tmpl"), join(out, ".github", "workflows", "ci.yml"));
package/src/init/init.ts CHANGED
@@ -80,7 +80,8 @@ export function renderSite(options: InitOptions): Array<[string, string]> {
80
80
  const manifest = JSON.parse(readFileSync(join(TEMPLATE, "package.json.tmpl"), "utf8")) as Record<string, unknown>;
81
81
  const dependencies: Record<string, string> = Object.fromEntries([
82
82
  ...CORE_PACKAGES.map((name) => [`@hearthlog/${name}`, own]),
83
- ...modules.map(({ manifest: { package: name } }) => [name, own]),
83
+ // A module is released on its own version, not on the platform's.
84
+ ...modules.map(({ manifest: { package: name }, directory }) => [name, workspace ? own : `^${(JSON.parse(readFileSync(join(directory, "package.json"), "utf8")) as { version: string }).version}`]),
84
85
  ["@hearthlog/generated", "link:.generated"],
85
86
  ].sort(([a], [b]) => a!.localeCompare(b!)));
86
87
  const devDependencies = Object.fromEntries(Object.entries(tooling.peerDependencies ?? {}).filter(([name]) => !name.startsWith("@hearthlog/")).sort(([a], [b]) => a.localeCompare(b)));
@@ -34,6 +34,11 @@ const SAFE_NOREPLY = /^(?:noreply@github\.com|[0-9]*\+?[a-z0-9-]+@users\.noreply
34
34
 
35
35
  /** Every file under the directory except `.git`, as relative paths. */
36
36
  export function listFiles(directory: string): string[] {
37
+ // In a repository, what could be pushed is what git tracks or would add: an ignored `node_modules` is not part of it.
38
+ if (existsSync(join(directory, ".git"))) {
39
+ const listed = execFileSync("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], { cwd: directory, maxBuffer: 256 * 1024 * 1024 });
40
+ return [...new Set(listed.toString("utf8").split("\0").filter(Boolean))].filter((file) => existsSync(join(directory, file)));
41
+ }
37
42
  const files: string[] = [];
38
43
  const walk = (current: string) => {
39
44
  for (const entry of readdirSync(current, { withFileTypes: true })) {
@@ -0,0 +1,11 @@
1
+ title = "hearthlog"
2
+
3
+ [extend]
4
+ useDefault = true
5
+
6
+ # Entity definitions name the fields of an event payload (`payloadKey: "caloriesPer100g"`); a field name that ends in
7
+ # digits and a letter looks like a key to the generic rule, but it is not a credential.
8
+ [[allowlists]]
9
+ description = "payloadKey names a payload field"
10
+ regexTarget = "line"
11
+ regexes = ['''payloadKey:\s*["'][A-Za-z0-9_]+["']''']
@@ -1,7 +1,7 @@
1
1
  name: Release
2
2
 
3
3
  # Set "version" in package.json, commit, then push the tag `v<version>`. The publish job waits for approval in the
4
- # protected `npm` environment; the registry credential is the organization secret NPM_TOKEN.
4
+ # protected `npm` environment; the package is published through npm's trusted publishing, so no registry token is stored.
5
5
  on:
6
6
  push:
7
7
  tags: ["v*"]
@@ -37,10 +37,16 @@ jobs:
37
37
  with:
38
38
  node-version: 24
39
39
  registry-url: https://registry.npmjs.org
40
+ # npm's trusted publishing (OIDC) needs npm 11.5.1 or later; no token is stored anywhere.
41
+ - run: npm install --global npm@11
40
42
  - run: pnpm install
41
- - run: pnpm publish --no-git-checks
42
- env:
43
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
43
+ - name: Publish the version in package.json unless the registry has it
44
+ run: |
45
+ name=$(node -p "require('./package.json').name")
46
+ version=$(node -p "require('./package.json').version")
47
+ if [ "$(npm view "$name@$version" version 2>/dev/null)" = "$version" ]; then echo "$name@$version is already published"; exit 0; fi
48
+ pnpm pack --pack-destination "$RUNNER_TEMP/pack"
49
+ npm publish "$RUNNER_TEMP/pack/"*.tgz --access public --provenance
44
50
 
45
51
  release:
46
52
  needs: publish
@@ -38,8 +38,6 @@ jobs:
38
38
  cache: pnpm
39
39
  - name: Install dependencies
40
40
  run: pnpm install --frozen-lockfile
41
- - name: Plan (read-only)
42
- run: pnpm exec hearthlog plan --site {{id}}
43
41
  - name: Build and seal
44
42
  env:
45
43
  VITE_STOR_TENANT: {{id}}
@@ -48,6 +46,9 @@ jobs:
48
46
  pnpm exec hearthlog gallery-public:build --site {{id}}
49
47
  pnpm exec vite build
50
48
  pnpm exec hearthlog artifact manifest --site {{id}}
49
+ # After the build: the plan reads the generated files the build writes.
50
+ - name: Plan (read-only)
51
+ run: pnpm exec hearthlog plan --site {{id}}
51
52
  - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
52
53
  with:
53
54
  name: release