@philkrpp/phase-loader 0.1.2 → 0.1.3

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 CHANGED
@@ -32,7 +32,8 @@ secrets: host, app ids, paths and keyring account names only.
32
32
  }
33
33
  },
34
34
  "require": ["DATABASE_URL"],
35
- "allowLiteral": []
35
+ "allowLiteral": [],
36
+ "external": ["WORKER_TIER"]
36
37
  }
37
38
  ```
38
39
 
@@ -45,6 +46,7 @@ secrets: host, app ids, paths and keyring account names only.
45
46
  | `targets.<name>.personal.account` | Optional keyring account holding a personal app id or name; exported last (path `/`). |
46
47
  | `require` | Keys the merged export must contain; otherwise loading fails and lists the missing names. |
47
48
  | `allowLiteral` | Keys whose value may start with `${`. Any other value starting with `${` is an unresolved Phase reference and fails the load. |
49
+ | `external` | Names set or read outside the Phase `dev` export: Coolify-only values, CI, runtime, variables read by libraries (`OTEL_*`). `example --write` lists them in their own section; `check` never reports them. |
48
50
 
49
51
  ## Tokens
50
52
 
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as KEYRING_SERVICE, c as loadConfig, l as PhaseLoaderError, n as fetchLayers, s as writeKeyring, t as run } from "./run-QGYeawST.js";
2
+ import { a as KEYRING_SERVICE, c as loadConfig, l as PhaseLoaderError, n as fetchLayers, s as writeKeyring, t as run } from "./run-CkwwrycO.js";
3
3
  import { existsSync, readFileSync, writeFileSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import { execFileSync } from "node:child_process";
@@ -35,7 +35,14 @@ function exampleNames(text) {
35
35
  * Returns the text to print; values are never read into the output.
36
36
  */
37
37
  async function example(opts = {}) {
38
- const { dir, sections } = await phaseNames(opts.cwd ?? process.cwd());
38
+ const cwd = opts.cwd ?? process.cwd();
39
+ const { dir, sections: phase } = await phaseNames(cwd);
40
+ const inPhase = new Set(phase.flatMap((s) => s.names));
41
+ const external = [...new Set(loadConfig(cwd).external)].filter((n) => !inPhase.has(n)).sort();
42
+ const sections = [...phase, {
43
+ label: "external (not loaded from Phase: Coolify, CI, runtime, libraries)",
44
+ names: external
45
+ }];
39
46
  const text = sections.filter((s) => s.names.length > 0).map((s) => `# ${s.label}\n${s.names.map((n) => `${n}=`).join("\n")}\n`).join("\n");
40
47
  const file = join(dir, EXAMPLE_FILE);
41
48
  if (opts.write) {
@@ -73,7 +80,17 @@ const BUILT_IN = /* @__PURE__ */ new Set([
73
80
  "SSR",
74
81
  "BASE_URL",
75
82
  "CI",
76
- "PHASE_ENV_LOADED"
83
+ "PHASE_ENV_LOADED",
84
+ "VITEST",
85
+ "PATH",
86
+ "HOME",
87
+ "USER",
88
+ "LOGNAME",
89
+ "SHELL",
90
+ "PWD",
91
+ "TMPDIR",
92
+ "TZ",
93
+ "LANG"
77
94
  ]);
78
95
  function trackedFiles(dir) {
79
96
  try {
@@ -114,15 +131,17 @@ function usedNames(dir) {
114
131
  * Online: also against the key names in Phase (`dev`). Names only, never values. `ok` is false on any finding.
115
132
  */
116
133
  async function check(opts = {}) {
117
- const dir = loadConfig(opts.cwd ?? process.cwd()).dir;
134
+ const config = loadConfig(opts.cwd ?? process.cwd());
135
+ const dir = config.dir;
118
136
  const file = join(dir, EXAMPLE_FILE);
119
137
  if (!existsSync(file)) throw new PhaseLoaderError(`${EXAMPLE_FILE} not found in ${dir} (create it with "phase-loader example --write").`);
138
+ const external = new Set(config.external);
120
139
  const documented = new Set(exampleNames(readFileSync(file, "utf8")));
121
140
  const { used, quoted } = usedNames(dir);
122
- const findings = [[`Used in code but undocumented in ${EXAMPLE_FILE}:`, [...used].filter((n) => !documented.has(n))], [`Orphan in ${EXAMPLE_FILE} (never read in tracked code):`, [...documented].filter((n) => !used.has(n) && !quoted.has(n))]];
141
+ const findings = [[`Used in code but undocumented in ${EXAMPLE_FILE}:`, [...used].filter((n) => !documented.has(n) && !external.has(n))], [`Orphan in ${EXAMPLE_FILE} (never read in tracked code):`, [...documented].filter((n) => !used.has(n) && !quoted.has(n) && !external.has(n))]];
123
142
  if (!opts.offline) {
124
143
  const inPhase = new Set((await phaseNames(opts.cwd ?? process.cwd())).sections.flatMap((s) => s.names));
125
- findings.push([`In ${EXAMPLE_FILE} but not in Phase:`, [...documented].filter((n) => !inPhase.has(n))], [`In Phase but not in ${EXAMPLE_FILE}:`, [...inPhase].filter((n) => !documented.has(n))]);
144
+ findings.push([`In ${EXAMPLE_FILE} but not in Phase:`, [...documented].filter((n) => !inPhase.has(n) && !external.has(n))], [`In Phase but not in ${EXAMPLE_FILE}:`, [...inPhase].filter((n) => !documented.has(n))]);
126
145
  }
127
146
  const lines = findings.filter(([, names]) => names.length > 0).flatMap(([title, names]) => [title, ` ${names.sort().join(", ")}`]);
128
147
  return lines.length > 0 ? {
package/dist/index.d.ts CHANGED
@@ -26,6 +26,11 @@ interface PhaseConfig {
26
26
  require: string[];
27
27
  /** Keys whose value may start with `${` (not a Phase reference). */
28
28
  allowLiteral: string[];
29
+ /**
30
+ * Names read or set outside the Phase `dev` export (Coolify-only values, CI, runtime, libraries such as OTEL_*):
31
+ * listed in their own `.env.example` section and never reported by `check`.
32
+ */
33
+ external: string[];
29
34
  }
30
35
  /** Finds the nearest `phase.config.json` from `cwd` upwards, validates and returns it. */
31
36
  export declare function loadConfig(cwd: string): PhaseConfig;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export { l as PhaseLoaderError, c as loadConfig, r as loadPhaseEnv, i as loadPhaseEnvSync, o as readToken, t as run } from "./run-QGYeawST.js";
1
+ export { l as PhaseLoaderError, c as loadConfig, r as loadPhaseEnv, i as loadPhaseEnvSync, o as readToken, t as run } from "./run-CkwwrycO.js";
@@ -84,7 +84,8 @@ function parseConfig(file, dir) {
84
84
  host,
85
85
  targets,
86
86
  require: keys(raw.require, "require"),
87
- allowLiteral: keys(raw.allowLiteral, "allowLiteral")
87
+ allowLiteral: keys(raw.allowLiteral, "allowLiteral"),
88
+ external: keys(raw.external, "external")
88
89
  };
89
90
  }
90
91
  function isObject$1(value) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@philkrpp/phase-loader",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Load env values from a self-hosted Phase secrets manager into a child process or the current process, with layered apps/paths and OS keyring tokens.",
5
5
  "license": "MIT",
6
6
  "repository": {