@superblocksteam/vite-plugin-file-sync 2.0.123-next.0 → 2.0.124-next.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/ai-service/agent/prompts/build-base-system-prompt.d.ts +16 -1
- package/dist/ai-service/agent/prompts/build-base-system-prompt.d.ts.map +1 -1
- package/dist/ai-service/agent/prompts/build-base-system-prompt.js +27 -1
- package/dist/ai-service/agent/prompts/build-base-system-prompt.js.map +1 -1
- package/dist/ai-service/agent/prompts/build-security-scan-prompt.d.ts.map +1 -1
- package/dist/ai-service/agent/prompts/build-security-scan-prompt.js +3 -1
- package/dist/ai-service/agent/prompts/build-security-scan-prompt.js.map +1 -1
- package/dist/ai-service/agent/tools/apis/api-comparator.d.ts.map +1 -1
- package/dist/ai-service/agent/tools/apis/api-comparator.js +1 -4
- package/dist/ai-service/agent/tools/apis/api-comparator.js.map +1 -1
- package/dist/ai-service/agent/tools/apis/api-testing-state.js +7 -0
- package/dist/ai-service/agent/tools/apis/api-testing-state.js.map +1 -1
- package/dist/ai-service/agent/tools/apis/get-api-docs.d.ts +1 -1
- package/dist/ai-service/agent/tools/apis/write-api.d.ts +2 -2
- package/dist/ai-service/agent/tools/build-capture-screenshot.d.ts.map +1 -1
- package/dist/ai-service/agent/tools/build-capture-screenshot.js +11 -33
- package/dist/ai-service/agent/tools/build-capture-screenshot.js.map +1 -1
- package/dist/ai-service/agent/tools/build-copy-directory.d.ts +1 -1
- package/dist/ai-service/agent/tools/build-finalize.d.ts.map +1 -1
- package/dist/ai-service/agent/tools/build-finalize.js +11 -2
- package/dist/ai-service/agent/tools/build-finalize.js.map +1 -1
- package/dist/ai-service/agent/tools/build-install-packages.d.ts +41 -1
- package/dist/ai-service/agent/tools/build-install-packages.d.ts.map +1 -1
- package/dist/ai-service/agent/tools/build-install-packages.js +208 -0
- package/dist/ai-service/agent/tools/build-install-packages.js.map +1 -1
- package/dist/ai-service/agent/tools/build-lookup-npm-package.d.ts +28 -0
- package/dist/ai-service/agent/tools/build-lookup-npm-package.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/build-lookup-npm-package.js +78 -0
- package/dist/ai-service/agent/tools/build-lookup-npm-package.js.map +1 -0
- package/dist/ai-service/agent/tools/build-manage-checklist.d.ts +4 -4
- package/dist/ai-service/agent/tools/build-navigate-preview.d.ts +16 -0
- package/dist/ai-service/agent/tools/build-navigate-preview.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/build-navigate-preview.js +68 -0
- package/dist/ai-service/agent/tools/build-navigate-preview.js.map +1 -0
- package/dist/ai-service/agent/tools/build-write-file.d.ts +1 -1
- package/dist/ai-service/agent/tools/databases/dev-database.d.ts +9 -9
- package/dist/ai-service/agent/tools/index.d.ts +2 -0
- package/dist/ai-service/agent/tools/index.d.ts.map +1 -1
- package/dist/ai-service/agent/tools/index.js +2 -0
- package/dist/ai-service/agent/tools/index.js.map +1 -1
- package/dist/ai-service/agent/tools/integrations/execute-request.d.ts +3 -3
- package/dist/ai-service/agent/tools/report-security-findings.d.ts +11 -5
- package/dist/ai-service/agent/tools/report-security-findings.d.ts.map +1 -1
- package/dist/ai-service/agent/tools/report-security-findings.js +1 -0
- package/dist/ai-service/agent/tools/report-security-findings.js.map +1 -1
- package/dist/ai-service/agent/tools.d.ts.map +1 -1
- package/dist/ai-service/agent/tools.js +3 -1
- package/dist/ai-service/agent/tools.js.map +1 -1
- package/dist/ai-service/agent/tools2/tools/git.d.ts +2 -2
- package/dist/ai-service/agent/tools2/tools/grep.d.ts +2 -2
- package/dist/ai-service/agent/tools2/tools/update-test-case-status.d.ts +2 -2
- package/dist/ai-service/app-interface/npm-error-parser.d.ts +161 -0
- package/dist/ai-service/app-interface/npm-error-parser.d.ts.map +1 -0
- package/dist/ai-service/app-interface/npm-error-parser.js +510 -0
- package/dist/ai-service/app-interface/npm-error-parser.js.map +1 -0
- package/dist/ai-service/app-interface/npm-package-lookup.d.ts +286 -0
- package/dist/ai-service/app-interface/npm-package-lookup.d.ts.map +1 -0
- package/dist/ai-service/app-interface/npm-package-lookup.js +793 -0
- package/dist/ai-service/app-interface/npm-package-lookup.js.map +1 -0
- package/dist/ai-service/app-interface/npm-registry.d.ts +735 -47
- package/dist/ai-service/app-interface/npm-registry.d.ts.map +1 -1
- package/dist/ai-service/app-interface/npm-registry.js +1882 -153
- package/dist/ai-service/app-interface/npm-registry.js.map +1 -1
- package/dist/ai-service/app-interface/shell.d.ts +118 -1
- package/dist/ai-service/app-interface/shell.d.ts.map +1 -1
- package/dist/ai-service/app-interface/shell.js +579 -157
- package/dist/ai-service/app-interface/shell.js.map +1 -1
- package/dist/ai-service/app-skills/manager.d.ts +1 -1
- package/dist/ai-service/app-skills/manager.d.ts.map +1 -1
- package/dist/ai-service/app-skills/manager.js +39 -7
- package/dist/ai-service/app-skills/manager.js.map +1 -1
- package/dist/ai-service/checklist/api-migration-checklist-gate.d.ts +9 -0
- package/dist/ai-service/checklist/api-migration-checklist-gate.d.ts.map +1 -0
- package/dist/ai-service/checklist/api-migration-checklist-gate.js +30 -0
- package/dist/ai-service/checklist/api-migration-checklist-gate.js.map +1 -0
- package/dist/ai-service/checklist/api-migration-origins.d.ts +4 -0
- package/dist/ai-service/checklist/api-migration-origins.d.ts.map +1 -0
- package/dist/ai-service/checklist/api-migration-origins.js +8 -0
- package/dist/ai-service/checklist/api-migration-origins.js.map +1 -0
- package/dist/ai-service/checklist/persisted-checklist-store.d.ts +2 -3
- package/dist/ai-service/checklist/persisted-checklist-store.d.ts.map +1 -1
- package/dist/ai-service/checklist/persisted-checklist-store.js +6 -7
- package/dist/ai-service/checklist/persisted-checklist-store.js.map +1 -1
- package/dist/ai-service/context-archive-paths.d.ts +4 -0
- package/dist/ai-service/context-archive-paths.d.ts.map +1 -0
- package/dist/ai-service/context-archive-paths.js +28 -0
- package/dist/ai-service/context-archive-paths.js.map +1 -0
- package/dist/ai-service/context-download.d.ts +3 -1
- package/dist/ai-service/context-download.d.ts.map +1 -1
- package/dist/ai-service/context-download.js +48 -9
- package/dist/ai-service/context-download.js.map +1 -1
- package/dist/ai-service/context-upload.d.ts +3 -2
- package/dist/ai-service/context-upload.d.ts.map +1 -1
- package/dist/ai-service/context-upload.js +44 -26
- package/dist/ai-service/context-upload.js.map +1 -1
- package/dist/ai-service/dev-database-client.d.ts +3 -11
- package/dist/ai-service/dev-database-client.d.ts.map +1 -1
- package/dist/ai-service/dev-database-client.js.map +1 -1
- package/dist/ai-service/features.d.ts +4 -0
- package/dist/ai-service/features.d.ts.map +1 -1
- package/dist/ai-service/features.js +8 -0
- package/dist/ai-service/features.js.map +1 -1
- package/dist/ai-service/filter-disabled-tools-for-migration.d.ts.map +1 -1
- package/dist/ai-service/filter-disabled-tools-for-migration.js +4 -0
- package/dist/ai-service/filter-disabled-tools-for-migration.js.map +1 -1
- package/dist/ai-service/index.d.ts +94 -0
- package/dist/ai-service/index.d.ts.map +1 -1
- package/dist/ai-service/index.js +564 -17
- package/dist/ai-service/index.js.map +1 -1
- package/dist/ai-service/llm/client.d.ts +38 -3
- package/dist/ai-service/llm/client.d.ts.map +1 -1
- package/dist/ai-service/llm/client.js +73 -22
- package/dist/ai-service/llm/client.js.map +1 -1
- package/dist/ai-service/llm/context-v2/adapter.d.ts +3 -1
- package/dist/ai-service/llm/context-v2/adapter.d.ts.map +1 -1
- package/dist/ai-service/llm/context-v2/adapter.js +11 -11
- package/dist/ai-service/llm/context-v2/adapter.js.map +1 -1
- package/dist/ai-service/llm/context-v2/compaction/client-side.d.ts +44 -0
- package/dist/ai-service/llm/context-v2/compaction/client-side.d.ts.map +1 -0
- package/dist/ai-service/llm/context-v2/compaction/client-side.js +170 -0
- package/dist/ai-service/llm/context-v2/compaction/client-side.js.map +1 -0
- package/dist/ai-service/llm/context-v2/compaction/compaction-strategy.d.ts +56 -0
- package/dist/ai-service/llm/context-v2/compaction/compaction-strategy.d.ts.map +1 -0
- package/dist/ai-service/llm/context-v2/compaction/compaction-strategy.js +9 -0
- package/dist/ai-service/llm/context-v2/compaction/compaction-strategy.js.map +1 -0
- package/dist/ai-service/llm/context-v2/compaction/index.d.ts +5 -0
- package/dist/ai-service/llm/context-v2/compaction/index.d.ts.map +1 -0
- package/dist/ai-service/llm/context-v2/compaction/index.js +3 -0
- package/dist/ai-service/llm/context-v2/compaction/index.js.map +1 -0
- package/dist/ai-service/llm/context-v2/compaction/server-side.d.ts +30 -0
- package/dist/ai-service/llm/context-v2/compaction/server-side.d.ts.map +1 -0
- package/dist/ai-service/llm/context-v2/compaction/server-side.js +130 -0
- package/dist/ai-service/llm/context-v2/compaction/server-side.js.map +1 -0
- package/dist/ai-service/llm/context-v2/context-management.d.ts +203 -0
- package/dist/ai-service/llm/context-v2/context-management.d.ts.map +1 -0
- package/dist/ai-service/llm/context-v2/context-management.js +183 -0
- package/dist/ai-service/llm/context-v2/context-management.js.map +1 -0
- package/dist/ai-service/llm/context-v2/context.d.ts +64 -22
- package/dist/ai-service/llm/context-v2/context.d.ts.map +1 -1
- package/dist/ai-service/llm/context-v2/context.js +233 -157
- package/dist/ai-service/llm/context-v2/context.js.map +1 -1
- package/dist/ai-service/llm/context-v2/conversation-context.d.ts +24 -7
- package/dist/ai-service/llm/context-v2/conversation-context.d.ts.map +1 -1
- package/dist/ai-service/llm/context-v2/conversation-context.js +1 -1
- package/dist/ai-service/llm/context-v2/index.d.ts +0 -4
- package/dist/ai-service/llm/context-v2/index.d.ts.map +1 -1
- package/dist/ai-service/llm/context-v2/index.js +0 -4
- package/dist/ai-service/llm/context-v2/index.js.map +1 -1
- package/dist/ai-service/llm/context-v2/manager.d.ts +24 -3
- package/dist/ai-service/llm/context-v2/manager.d.ts.map +1 -1
- package/dist/ai-service/llm/context-v2/manager.js +146 -4
- package/dist/ai-service/llm/context-v2/manager.js.map +1 -1
- package/dist/ai-service/llm/context-v2/migrations/v1-to-v2.d.ts +2 -7
- package/dist/ai-service/llm/context-v2/migrations/v1-to-v2.d.ts.map +1 -1
- package/dist/ai-service/llm/context-v2/migrations/v1-to-v2.js +5 -73
- package/dist/ai-service/llm/context-v2/migrations/v1-to-v2.js.map +1 -1
- package/dist/ai-service/llm/context-v2/storage/event-store.d.ts +57 -0
- package/dist/ai-service/llm/context-v2/storage/event-store.d.ts.map +1 -0
- package/dist/ai-service/llm/context-v2/storage/event-store.js +10 -0
- package/dist/ai-service/llm/context-v2/storage/event-store.js.map +1 -0
- package/dist/ai-service/llm/context-v2/storage/event-types.d.ts +50 -0
- package/dist/ai-service/llm/context-v2/storage/event-types.d.ts.map +1 -0
- package/dist/ai-service/llm/context-v2/storage/event-types.js +10 -0
- package/dist/ai-service/llm/context-v2/storage/event-types.js.map +1 -0
- package/dist/ai-service/llm/context-v2/storage/jsonl-event-store.d.ts +87 -0
- package/dist/ai-service/llm/context-v2/storage/jsonl-event-store.d.ts.map +1 -0
- package/dist/ai-service/llm/context-v2/storage/jsonl-event-store.js +184 -0
- package/dist/ai-service/llm/context-v2/storage/jsonl-event-store.js.map +1 -0
- package/dist/ai-service/llm/context-v2/storage/migration.d.ts +49 -0
- package/dist/ai-service/llm/context-v2/storage/migration.d.ts.map +1 -0
- package/dist/ai-service/llm/context-v2/storage/migration.js +126 -0
- package/dist/ai-service/llm/context-v2/storage/migration.js.map +1 -0
- package/dist/ai-service/llm/context-v2/types.d.ts +16 -11
- package/dist/ai-service/llm/context-v2/types.d.ts.map +1 -1
- package/dist/ai-service/llm/context-v2/types.js +2 -2
- package/dist/ai-service/llm/context-v2/types.js.map +1 -1
- package/dist/ai-service/llm/impl/clark.d.ts +8 -0
- package/dist/ai-service/llm/impl/clark.d.ts.map +1 -1
- package/dist/ai-service/llm/impl/clark.js +8 -0
- package/dist/ai-service/llm/impl/clark.js.map +1 -1
- package/dist/ai-service/llm/interaction/adapters/vercel.d.ts.map +1 -1
- package/dist/ai-service/llm/interaction/adapters/vercel.js +17 -1
- package/dist/ai-service/llm/interaction/adapters/vercel.js.map +1 -1
- package/dist/ai-service/llm/provider.d.ts.map +1 -1
- package/dist/ai-service/llm/provider.js +1 -3
- package/dist/ai-service/llm/provider.js.map +1 -1
- package/dist/ai-service/llm/stream/observers/context.d.ts +23 -0
- package/dist/ai-service/llm/stream/observers/context.d.ts.map +1 -1
- package/dist/ai-service/llm/stream/observers/context.js +62 -0
- package/dist/ai-service/llm/stream/observers/context.js.map +1 -1
- package/dist/ai-service/llm/tool-context-integrity.d.ts +25 -0
- package/dist/ai-service/llm/tool-context-integrity.d.ts.map +1 -0
- package/dist/ai-service/llm/tool-context-integrity.js +141 -0
- package/dist/ai-service/llm/tool-context-integrity.js.map +1 -0
- package/dist/ai-service/skills/system/superblocks-migration/skill.generated.d.ts +1 -1
- package/dist/ai-service/skills/system/superblocks-migration/skill.generated.d.ts.map +1 -1
- package/dist/ai-service/skills/system/superblocks-migration/skill.generated.js +6 -1
- package/dist/ai-service/skills/system/superblocks-migration/skill.generated.js.map +1 -1
- package/dist/ai-service/skills/system/third-party-migration/skill.generated.d.ts +1 -1
- package/dist/ai-service/skills/system/third-party-migration/skill.generated.d.ts.map +1 -1
- package/dist/ai-service/skills/system/third-party-migration/skill.generated.js +3 -2
- package/dist/ai-service/skills/system/third-party-migration/skill.generated.js.map +1 -1
- package/dist/ai-service/state-machine/clark-fsm.d.ts +23 -2
- package/dist/ai-service/state-machine/clark-fsm.d.ts.map +1 -1
- package/dist/ai-service/state-machine/clark-fsm.js +37 -2
- package/dist/ai-service/state-machine/clark-fsm.js.map +1 -1
- package/dist/ai-service/state-machine/handlers/agent-planning.d.ts.map +1 -1
- package/dist/ai-service/state-machine/handlers/agent-planning.js +29 -2
- package/dist/ai-service/state-machine/handlers/agent-planning.js.map +1 -1
- package/dist/ai-service/state-machine/handlers/awaiting-user.d.ts.map +1 -1
- package/dist/ai-service/state-machine/handlers/awaiting-user.js +9 -0
- package/dist/ai-service/state-machine/handlers/awaiting-user.js.map +1 -1
- package/dist/ai-service/state-machine/handlers/llm-generating.d.ts.map +1 -1
- package/dist/ai-service/state-machine/handlers/llm-generating.js +25 -2
- package/dist/ai-service/state-machine/handlers/llm-generating.js.map +1 -1
- package/dist/ai-service/state-machine/helpers/fetch-with-reconnect-retry.d.ts +6 -0
- package/dist/ai-service/state-machine/helpers/fetch-with-reconnect-retry.d.ts.map +1 -0
- package/dist/ai-service/state-machine/helpers/fetch-with-reconnect-retry.js +36 -0
- package/dist/ai-service/state-machine/helpers/fetch-with-reconnect-retry.js.map +1 -0
- package/dist/ai-service/state-machine/helpers/stable-peer.d.ts +30 -1
- package/dist/ai-service/state-machine/helpers/stable-peer.d.ts.map +1 -1
- package/dist/ai-service/state-machine/helpers/stable-peer.js +85 -2
- package/dist/ai-service/state-machine/helpers/stable-peer.js.map +1 -1
- package/dist/ai-service/state-machine/helpers/user-preferences.d.ts +8 -0
- package/dist/ai-service/state-machine/helpers/user-preferences.d.ts.map +1 -0
- package/dist/ai-service/state-machine/helpers/user-preferences.js +11 -0
- package/dist/ai-service/state-machine/helpers/user-preferences.js.map +1 -0
- package/dist/ai-service/template-renderer.d.ts +18 -1
- package/dist/ai-service/template-renderer.d.ts.map +1 -1
- package/dist/ai-service/template-renderer.js +73 -12
- package/dist/ai-service/template-renderer.js.map +1 -1
- package/dist/ai-service/types.d.ts +157 -0
- package/dist/ai-service/types.d.ts.map +1 -1
- package/dist/ai-service/types.js +137 -0
- package/dist/ai-service/types.js.map +1 -1
- package/dist/ai-service/util/llm-config-utils.d.ts +21 -22
- package/dist/ai-service/util/llm-config-utils.d.ts.map +1 -1
- package/dist/ai-service/util/llm-config-utils.js +40 -67
- package/dist/ai-service/util/llm-config-utils.js.map +1 -1
- package/dist/file-sync-vite-plugin.d.ts.map +1 -1
- package/dist/file-sync-vite-plugin.js +5 -0
- package/dist/file-sync-vite-plugin.js.map +1 -1
- package/dist/file-system-helpers.d.ts +17 -0
- package/dist/file-system-helpers.d.ts.map +1 -1
- package/dist/file-system-helpers.js +22 -0
- package/dist/file-system-helpers.js.map +1 -1
- package/dist/git-service/index.d.ts.map +1 -1
- package/dist/git-service/index.js +15 -1
- package/dist/git-service/index.js.map +1 -1
- package/dist/migration/migration-routes.d.ts.map +1 -1
- package/dist/migration/migration-routes.js +26 -3
- package/dist/migration/migration-routes.js.map +1 -1
- package/dist/migration/translation-prompt.d.ts.map +1 -1
- package/dist/migration/translation-prompt.js +5 -0
- package/dist/migration/translation-prompt.js.map +1 -1
- package/dist/migration-templates/app-fullstack/package.json +2 -2
- package/dist/policy-gate-callback-mapper.d.ts +24 -0
- package/dist/policy-gate-callback-mapper.d.ts.map +1 -0
- package/dist/policy-gate-callback-mapper.js +61 -0
- package/dist/policy-gate-callback-mapper.js.map +1 -0
- package/dist/policy-gate-runner.d.ts +32 -0
- package/dist/policy-gate-runner.d.ts.map +1 -0
- package/dist/policy-gate-runner.js +191 -0
- package/dist/policy-gate-runner.js.map +1 -0
- package/dist/router-parser.d.ts.map +1 -1
- package/dist/router-parser.js +107 -11
- package/dist/router-parser.js.map +1 -1
- package/dist/sync-service/list-dir.d.ts.map +1 -1
- package/dist/sync-service/list-dir.js +13 -3
- package/dist/sync-service/list-dir.js.map +1 -1
- package/package.json +28 -10
|
@@ -9,84 +9,737 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export declare const PRESERVE_NPMRC_SCOPES: string[];
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* Wire shape for a single registry row returned by
|
|
13
|
+
* `GET /api/v1/organizations/:orgId/npm-registry`. Mirrors the server's
|
|
14
|
+
* `OrgNpmRegistryDto` (see
|
|
15
|
+
* `packages/server/src/controllers/v1/orgNpmRegistry/handlers.ts`).
|
|
13
16
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
|
|
17
|
+
* `scope === null` is the default (unscoped) registry; otherwise it is a
|
|
18
|
+
* single npm scope like `"@mycompany"`.
|
|
19
|
+
*/
|
|
20
|
+
export interface NpmRegistryEntry {
|
|
21
|
+
id: string;
|
|
22
|
+
scope: string | null;
|
|
23
|
+
registryUrl: string;
|
|
24
|
+
token: string | null;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Renderable npm registry configuration. This is the shape `writeNpmrc`
|
|
28
|
+
* consumes — it is independent of where it came from (server fetch in
|
|
29
|
+
* production; constructed in tests). For a configured org, `default` is
|
|
30
|
+
* populated; for an org with no registries, both fields are empty and
|
|
31
|
+
* `configured` is false.
|
|
17
32
|
*/
|
|
18
33
|
export interface NpmRegistryConfig {
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
|
|
34
|
+
/** True if at least one registry is configured for the org. */
|
|
35
|
+
configured: boolean;
|
|
36
|
+
/** Default (unscoped) registry URL + optional token. */
|
|
37
|
+
default?: {
|
|
38
|
+
url: string;
|
|
39
|
+
token?: string;
|
|
40
|
+
};
|
|
23
41
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
42
|
+
* Scoped registries keyed by scope (e.g. `"@mycompany"`).
|
|
43
|
+
* Tokens are kept alongside so `writeNpmrc` can emit per-scope
|
|
44
|
+
* `_authToken=` lines.
|
|
26
45
|
*/
|
|
27
|
-
scopes?: Record<string,
|
|
46
|
+
scopes?: Record<string, {
|
|
47
|
+
url: string;
|
|
48
|
+
token?: string;
|
|
49
|
+
}>;
|
|
50
|
+
/**
|
|
51
|
+
* Org-level npm policy: `false` means AppShell appends `--ignore-scripts`
|
|
52
|
+
* to every npm/pnpm invocation; `true` or `undefined` keeps the default
|
|
53
|
+
* behaviour. Independent of `configured` — an org can set the policy
|
|
54
|
+
* without configuring any registry rows (in which case `configured` is
|
|
55
|
+
* false but the policy still flows through). Originates from the
|
|
56
|
+
* `superblocks.npm-registry.enabled` LD-flag-gated field on the server
|
|
57
|
+
* (APPS-4250); undefined when the flag is off or the server omits it.
|
|
58
|
+
*/
|
|
59
|
+
allowInstallScripts?: boolean;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Logical outcome of `NpmRegistryClient.getConfig()`. The discriminator lets
|
|
63
|
+
* callers branch cleanly on the four cases without inspecting the cache
|
|
64
|
+
* itself.
|
|
65
|
+
*
|
|
66
|
+
* - `configured`: at least one registry row exists for the org; render
|
|
67
|
+
* `.npmrc` lines from `config`.
|
|
68
|
+
* - `not-configured`: a successful server observation said the org has
|
|
69
|
+
* no registry rows (flag off, 404, or empty `registries: []`). Caller
|
|
70
|
+
* can act on this as deliberate steady-state — e.g. cleanup of a
|
|
71
|
+
* previously-written `.npmrc`. Downstream `require` enforcement (when
|
|
72
|
+
* wired) decides whether to refuse npm.
|
|
73
|
+
* - `stale`: server unreachable, returning last-known-good non-empty
|
|
74
|
+
* entries. Same render path as `configured`, but the source field
|
|
75
|
+
* distinguishes it for observability and tests.
|
|
76
|
+
* - `unreachable`: server unreachable AND we have no usable cache (cold
|
|
77
|
+
* start or only an empty observation). `config.configured` is false so
|
|
78
|
+
* write-side consumers (`maybeWriteNpmrcForDir`, `prepareForPrivateRegistry`)
|
|
79
|
+
* no-op safely. Distinct from `not-configured` so consumers with
|
|
80
|
+
* destructive cleanup paths (e.g. `syncHomeNpmrc`) can refuse to act
|
|
81
|
+
* on what is really "we don't know" rather than "deliberately unset".
|
|
82
|
+
*/
|
|
83
|
+
export type NpmRegistryFetchResult = {
|
|
84
|
+
source: "configured";
|
|
85
|
+
config: NpmRegistryConfig;
|
|
86
|
+
} | {
|
|
87
|
+
source: "stale";
|
|
88
|
+
config: NpmRegistryConfig;
|
|
89
|
+
} | {
|
|
90
|
+
source: "not-configured";
|
|
91
|
+
config: NpmRegistryConfig;
|
|
92
|
+
} | {
|
|
93
|
+
source: "unreachable";
|
|
94
|
+
config: NpmRegistryConfig;
|
|
28
95
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
96
|
+
* APPS-4370. True if a `LastKnownRegistryPolicyStore` was wired into
|
|
97
|
+
* the `NpmRegistryClient` and reported that this org had at some prior
|
|
98
|
+
* point successfully resolved a configured registry (i.e. a marker file
|
|
99
|
+
* exists on disk). Used by AppShell install paths to fail closed with
|
|
100
|
+
* `NpmInstallBlocked(registry_unreachable)` rather than silently
|
|
101
|
+
* resolving through public npm during a server outage.
|
|
102
|
+
*
|
|
103
|
+
* - `true` — store reports a prior successful fetch; the install
|
|
104
|
+
* path MUST refuse to spawn npm.
|
|
105
|
+
* - `false` — store has no marker (first-install / greenfield);
|
|
106
|
+
* the install path proceeds as before so cold-boot
|
|
107
|
+
* first-time users are not blocked.
|
|
108
|
+
* - `undefined` — no store was wired in at all (test fixtures, older
|
|
109
|
+
* call sites). Install path falls back to current
|
|
110
|
+
* behaviour (proceed).
|
|
32
111
|
*/
|
|
33
|
-
|
|
112
|
+
everConfigured?: boolean;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* APPS-4370. Disk-backed per-org "this org has at some point been configured
|
|
116
|
+
* with a private npm registry" marker. The CLI's `NpmRegistryClient` writes
|
|
117
|
+
* the marker on every `configured` / `stale` resolution and reads it on
|
|
118
|
+
* `unreachable` so AppShell's install paths can fail closed with
|
|
119
|
+
* `NpmInstallBlocked(registry_unreachable)` on a server outage — rather than
|
|
120
|
+
* silently resolving through public npm with a possibly-stale managed
|
|
121
|
+
* `.npmrc`.
|
|
122
|
+
*
|
|
123
|
+
* Implementations MUST be best-effort: a write failure (disk full,
|
|
124
|
+
* permission denied) MUST NOT throw, and a read failure MUST resolve to
|
|
125
|
+
* `false` rather than rejecting. Either is a strict superset of today's
|
|
126
|
+
* behaviour (no marker → proceed), so a broken store keeps the install
|
|
127
|
+
* path healthy.
|
|
128
|
+
*/
|
|
129
|
+
export interface LastKnownRegistryPolicyStore {
|
|
130
|
+
/** Persist the per-org marker. Best-effort; never throws. */
|
|
131
|
+
markConfigured(): Promise<void>;
|
|
132
|
+
/** True if the marker is present. Best-effort; resolves to false on error. */
|
|
133
|
+
hasEverBeenConfigured(): Promise<boolean>;
|
|
34
134
|
}
|
|
35
135
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
136
|
+
* Resolves the org `allow_install_scripts` policy from a `prepareForPrivateRegistry`
|
|
137
|
+
* (or `maybeWriteNpmrcForDir`) result. `false` means "the org has explicitly
|
|
138
|
+
* disabled npm install scripts" — install entrypoints append `--ignore-scripts`.
|
|
139
|
+
* `true` or `undefined` (server omitted the field, LD flag off, no client wired
|
|
140
|
+
* up) keeps today's behaviour.
|
|
41
141
|
*
|
|
42
|
-
*
|
|
43
|
-
* -
|
|
44
|
-
*
|
|
45
|
-
* - SUPERBLOCKS_NPM_REGISTRY_SCOPES_JSON: optional JSON map of scope -> URL
|
|
46
|
-
* - SUPERBLOCKS_REQUIRE_PRIVATE_REGISTRY: opt-in strict mode (default off)
|
|
142
|
+
* Shared by AppShell install entrypoints (shell.ts) and the dev-server startup
|
|
143
|
+
* install (sdk/cli-replacement/dev.mts) so both paths interpret the policy
|
|
144
|
+
* identically.
|
|
47
145
|
*/
|
|
48
|
-
export declare function
|
|
146
|
+
export declare function shouldIgnoreInstallScripts(result: NpmRegistryFetchResult | undefined): boolean;
|
|
147
|
+
/**
|
|
148
|
+
* Translates a list of server-shaped registry entries into the renderable
|
|
149
|
+
* `NpmRegistryConfig`. Centralised so `writeNpmrc`, tests, and any future
|
|
150
|
+
* consumer all interpret the wire shape the same way.
|
|
151
|
+
*
|
|
152
|
+
* Multiple `scope === null` entries should never happen — the server's
|
|
153
|
+
* UNIQUE (organization_id, scope) constraint forbids it — but we are
|
|
154
|
+
* defensive: the FIRST default wins, subsequent ones are logged and
|
|
155
|
+
* discarded so a server-side bug never silently rotates the default URL
|
|
156
|
+
* mid-fetch.
|
|
157
|
+
*
|
|
158
|
+
* Duplicate scoped entries (same `scope` string) follow the same rule:
|
|
159
|
+
* first wins.
|
|
160
|
+
*/
|
|
161
|
+
export declare function registriesToConfig(entries: NpmRegistryEntry[], allowInstallScripts?: boolean): NpmRegistryConfig;
|
|
162
|
+
/**
|
|
163
|
+
* Dependencies the `NpmRegistryClient` needs to fetch from the server.
|
|
164
|
+
* Injected so the client itself stays free of `fs`, `~/.superblocks/auth.json`
|
|
165
|
+
* parsing, and LaunchDarkly client wiring — those live at the dev-server
|
|
166
|
+
* entrypoint / CLI bootstrap layer and are exercised by their own tests.
|
|
167
|
+
*/
|
|
168
|
+
export interface NpmRegistryClientDeps {
|
|
169
|
+
/**
|
|
170
|
+
* Returns true if the `superblocks.npm-registry.enabled` LaunchDarkly
|
|
171
|
+
* flag is on for the active org. Called on every `getConfig()` because LD
|
|
172
|
+
* flag flips must propagate within the LD poll interval without a process
|
|
173
|
+
* restart (see APPS-4228 acceptance).
|
|
174
|
+
*
|
|
175
|
+
* Synchronous on purpose: the caller has already evaluated the flag
|
|
176
|
+
* against the org context; the client just reads the current value.
|
|
177
|
+
*/
|
|
178
|
+
isFlagEnabled: () => boolean;
|
|
179
|
+
/**
|
|
180
|
+
* Returns the current user JWT for the active dev-server session.
|
|
181
|
+
* Called once per fetch attempt; on 401 the client first awaits
|
|
182
|
+
* `refreshJwt` (if provided) and then re-invokes this for the retry.
|
|
183
|
+
*/
|
|
184
|
+
getJwt: () => Promise<string>;
|
|
185
|
+
/**
|
|
186
|
+
* Optional hook the client awaits between a 401 and its retry. The
|
|
187
|
+
* intended implementation subscribes once to a push-based token
|
|
188
|
+
* refresh signal (e.g. `tokenManager`'s `tokenUpdated` event) with a
|
|
189
|
+
* short timeout, so the retry has a fair chance of picking up a
|
|
190
|
+
* freshly-rotated JWT.
|
|
191
|
+
*
|
|
192
|
+
* If omitted, the client retries immediately with the next `getJwt()`
|
|
193
|
+
* read — useful for tests and for environments where no push-based
|
|
194
|
+
* refresh exists. The retry still benefits from any external refresh
|
|
195
|
+
* that happens to have landed by the time `getJwt()` is re-read; it
|
|
196
|
+
* just isn't given the chance to wait.
|
|
197
|
+
*
|
|
198
|
+
* Errors thrown by `refreshJwt` are treated as transient: the client
|
|
199
|
+
* routes through `serveStaleOrUnconfigured` rather than crashing the
|
|
200
|
+
* install path on a refresh-channel hiccup.
|
|
201
|
+
*/
|
|
202
|
+
refreshJwt?: () => Promise<void>;
|
|
203
|
+
/** Active organization id. */
|
|
204
|
+
organizationId: string;
|
|
205
|
+
/**
|
|
206
|
+
* Base URL of the Superblocks server (e.g. `https://app.superblocks.com`,
|
|
207
|
+
* `http://localhost:3000`). The client appends
|
|
208
|
+
* `/api/v1/organizations/:orgId/npm-registry`.
|
|
209
|
+
*/
|
|
210
|
+
baseUrl: string;
|
|
211
|
+
/**
|
|
212
|
+
* Optional `fetch` override for testing. Defaults to the global `fetch`
|
|
213
|
+
* available in Node 18+.
|
|
214
|
+
*/
|
|
215
|
+
fetch?: typeof globalThis.fetch;
|
|
216
|
+
/**
|
|
217
|
+
* TTL for the in-memory cache, in milliseconds. Defaults to 5 minutes,
|
|
218
|
+
* matching the ticket's tunable.
|
|
219
|
+
*/
|
|
220
|
+
ttlMs?: number;
|
|
221
|
+
/**
|
|
222
|
+
* Clock function returning the current time in ms. Defaults to
|
|
223
|
+
* `Date.now`. Overridable so tests can advance the cache deterministically
|
|
224
|
+
* without `vi.useFakeTimers()`.
|
|
225
|
+
*/
|
|
226
|
+
now?: () => number;
|
|
227
|
+
/**
|
|
228
|
+
* APPS-4370. Optional disk-backed store the client uses to record that
|
|
229
|
+
* an org has at some point successfully resolved a configured registry,
|
|
230
|
+
* and to consult on `unreachable` resolutions so the result can carry
|
|
231
|
+
* `everConfigured` for the AppShell install fail-closed decision.
|
|
232
|
+
*
|
|
233
|
+
* When omitted, the client behaves exactly as before: marker writes are
|
|
234
|
+
* silently skipped and `unreachable` results carry no `everConfigured`
|
|
235
|
+
* field. Install paths that key off the field default to "proceed".
|
|
236
|
+
*
|
|
237
|
+
* Writes are fire-and-forget: a `markConfigured()` rejection is logged
|
|
238
|
+
* but never bubbles up to the install path.
|
|
239
|
+
*/
|
|
240
|
+
lastKnownPolicyStore?: LastKnownRegistryPolicyStore;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Fetches per-org npm registry configuration from the server, caching the
|
|
244
|
+
* result in-memory with a short TTL. Designed so callers do not have to
|
|
245
|
+
* think about the LaunchDarkly flag, JWT lifecycle, or transient server
|
|
246
|
+
* outages — they just `await client.getConfig()` and get back a renderable
|
|
247
|
+
* shape (or "not configured").
|
|
248
|
+
*
|
|
249
|
+
* Lifecycle invariants (see APPS-4230 scope):
|
|
250
|
+
*
|
|
251
|
+
* 1. **Flag off → short-circuit**: returns `{ configured: false }` with
|
|
252
|
+
* no network I/O. Lets us dark-ship LinkedIn first without hammering
|
|
253
|
+
* the API for the rest of the fleet.
|
|
254
|
+
* 2. **Cache hit within TTL → no fetch**: avoids per-install round-trips
|
|
255
|
+
* against the server.
|
|
256
|
+
* 3. **401 → await `refreshJwt` then retry once with a fresh
|
|
257
|
+
* `getJwt()` read**: any push-based JWT refresh (auth-hot-reload)
|
|
258
|
+
* that landed between the original request and the retry is picked
|
|
259
|
+
* up. The cache is preserved across the retry so a failed retry
|
|
260
|
+
* can still fall back to last-known-good. Two disjoint failure
|
|
261
|
+
* modes:
|
|
262
|
+
* - The retry itself returns 401 → hard throw. We deliberately do
|
|
263
|
+
* not keep retrying because the only way a freshly-read JWT also
|
|
264
|
+
* 401s is a true re-auth failure.
|
|
265
|
+
* - `refreshJwt` itself throws or times out (e.g. the push channel
|
|
266
|
+
* hung) → route through `serveStaleOrUnconfigured` (same as a 5xx
|
|
267
|
+
* / network outage). A flaky refresh channel must not crash the
|
|
268
|
+
* install path, and we never reach the second `attempt()`.
|
|
269
|
+
* 4. **Other 4xx (403/400/…) → clear the cache and throw**: these are
|
|
270
|
+
* deliberate denials (RBAC revocation, malformed request), not
|
|
271
|
+
* transient outages. Serving stale would extend the revocation
|
|
272
|
+
* window beyond the cache TTL. The error propagates to the caller
|
|
273
|
+
* (typically `AppShell` / `TemplateRenderer`), which decides
|
|
274
|
+
* whether to fail the install or fall back to public npm.
|
|
275
|
+
* 5. **5xx or network unreachable + cached value → return cache +
|
|
276
|
+
* `logger.warn`**: install workflows continue against the
|
|
277
|
+
* last-known-good registry while we surface the outage; strictly
|
|
278
|
+
* better than falling back to `registry.npmjs.org` mid-deploy.
|
|
279
|
+
* 6. **5xx or network unreachable + no usable cache → return
|
|
280
|
+
* `source: "unreachable"` with `{ configured: false }`**: cold start
|
|
281
|
+
* or only an empty-list cache. `config.configured: false` so
|
|
282
|
+
* write-side consumers continue to no-op, but the distinct source
|
|
283
|
+
* keeps destructive cleanup paths (home-npmrc unlink) from acting on
|
|
284
|
+
* a transient outage.
|
|
285
|
+
*
|
|
286
|
+
* The class is intentionally a thin wrapper around a single Map cell — the
|
|
287
|
+
* cache key is `(organizationId)` since one client serves one org. Sharing
|
|
288
|
+
* one client across orgs would require per-org cache keys; we don't do
|
|
289
|
+
* that today because the dev-server pod is single-tenant.
|
|
290
|
+
*/
|
|
291
|
+
export declare class NpmRegistryClient {
|
|
292
|
+
private readonly deps;
|
|
293
|
+
/**
|
|
294
|
+
* Last successful fetch + when it landed. Source of both the TTL check
|
|
295
|
+
* and the last-known-good fallback. We deliberately store the entries as
|
|
296
|
+
* received (not the rendered `NpmRegistryConfig`) so future readers can
|
|
297
|
+
* apply different render policies without a re-fetch.
|
|
298
|
+
*
|
|
299
|
+
* `npmAllowInstallScripts` rides alongside because the server returns it
|
|
300
|
+
* on the same envelope and AppShell wants the same TTL/fallback semantics
|
|
301
|
+
* for both. `undefined` here means the server omitted the field (LD flag
|
|
302
|
+
* off on the server side, or older server); we propagate that as
|
|
303
|
+
* `allowInstallScripts: undefined` rather than defaulting to `true` so
|
|
304
|
+
* the consumer can distinguish "policy known, scripts allowed" from
|
|
305
|
+
* "policy unknown".
|
|
306
|
+
*/
|
|
307
|
+
private cache;
|
|
308
|
+
/**
|
|
309
|
+
* Inflight `fetchWithRefresh()` promise, if any. Used to deduplicate
|
|
310
|
+
* concurrent `getConfig()` callers during a cache miss (or stale-after-
|
|
311
|
+
* TTL re-fetch): rather than firing N network requests for N callers
|
|
312
|
+
* we share the single in-flight request. Cleared in a `.finally()` so a
|
|
313
|
+
* resolved or rejected fetch never sticks around.
|
|
314
|
+
*
|
|
315
|
+
* Without this, a burst of installs that all hit cold cache would race
|
|
316
|
+
* to the server, the first one's 401 would clear the cache for itself
|
|
317
|
+
* before the others observe their own 401s — and the others would
|
|
318
|
+
* then have no last-known-good to fall back to.
|
|
319
|
+
*/
|
|
320
|
+
private inflight;
|
|
321
|
+
/**
|
|
322
|
+
* Last `npmAllowInstallScripts` value observed from a successful server
|
|
323
|
+
* response, retained across hard-fail cache invalidations (refreshJwt
|
|
324
|
+
* rejection, double-401, other 4xx). Registry credentials and the
|
|
325
|
+
* security policy live on the same envelope but have different
|
|
326
|
+
* security semantics: serving stale credentials to a revoked caller
|
|
327
|
+
* extends a deliberate denial, but dropping a known `false` policy
|
|
328
|
+
* silently weakens `--ignore-scripts` enforcement — strictly the
|
|
329
|
+
* wrong direction. So `this.cache` is cleared on hard-fail (revoke
|
|
330
|
+
* stale credentials), but this field survives so the next call's
|
|
331
|
+
* fall-through `serveStaleOrUnconfigured` still propagates the
|
|
332
|
+
* org's policy to AppShell.
|
|
333
|
+
*/
|
|
334
|
+
private lastKnownPolicy;
|
|
335
|
+
constructor(deps: NpmRegistryClientDeps);
|
|
336
|
+
/**
|
|
337
|
+
* Clears the in-memory cache so the next `getConfig()` re-fetches from
|
|
338
|
+
* the server. Called by AppShell install retry when
|
|
339
|
+
* `registry_auth_failed` indicates a stale Artifactory token.
|
|
340
|
+
*
|
|
341
|
+
* `lastKnownPolicy` survives invalidation (same as the auth-failure
|
|
342
|
+
* branches in `fetchWithRefresh`) so `--ignore-scripts` enforcement
|
|
343
|
+
* is not weakened during the re-fetch.
|
|
344
|
+
*/
|
|
345
|
+
invalidateCache(): void;
|
|
346
|
+
/**
|
|
347
|
+
* Persist the "ever configured" marker, AWAITED so the write is durable
|
|
348
|
+
* before the caller hands back a `configured` / `stale` resolution. Used
|
|
349
|
+
* on every such resolution so a subsequent server outage can fail closed
|
|
350
|
+
* instead of silently resolving through public npm.
|
|
351
|
+
*
|
|
352
|
+
* Awaited (not fire-and-forget) because the marker must be on disk before
|
|
353
|
+
* `getConfig()` returns: a crash in the gap between returning `configured`
|
|
354
|
+
* and an un-awaited write landing would lose the marker and silently break
|
|
355
|
+
* the "once configured, always fail-closed on unreachable" invariant. The
|
|
356
|
+
* write stays async (`fs/promises`, per the ai-service no-sync-fs rule);
|
|
357
|
+
* the disk store guards itself so the write happens at most once per
|
|
358
|
+
* process (see `createDiskRegistryPolicyStore`), keeping the awaited write
|
|
359
|
+
* off the hot path after the first configured resolution.
|
|
360
|
+
*
|
|
361
|
+
* Logs a warning on write failure but never propagates the error: a broken
|
|
362
|
+
* store is a strict superset of today's no-marker behaviour, and the
|
|
363
|
+
* install path must stay healthy when disk is full or the marker directory
|
|
364
|
+
* is unwritable.
|
|
365
|
+
*/
|
|
366
|
+
private markPolicyConfigured;
|
|
367
|
+
/**
|
|
368
|
+
* Read the disk-backed marker that AppShell uses to decide whether to
|
|
369
|
+
* fail closed on `unreachable`. Treats a read failure as `false` so a
|
|
370
|
+
* transient store IO error preserves current behaviour (proceed) rather
|
|
371
|
+
* than degrading to a fail-closed install.
|
|
372
|
+
*/
|
|
373
|
+
private readEverConfigured;
|
|
374
|
+
/**
|
|
375
|
+
* Resolve the current npm registry configuration for the active org. See
|
|
376
|
+
* the class docstring for the full state machine.
|
|
377
|
+
*/
|
|
378
|
+
getConfig(): Promise<NpmRegistryFetchResult>;
|
|
379
|
+
private fetchWithRefresh;
|
|
380
|
+
/**
|
|
381
|
+
* One full fetch attempt with the current JWT. Throws on getJwt failure
|
|
382
|
+
* OR network failure so the caller's single try/catch handles both.
|
|
383
|
+
*/
|
|
384
|
+
private attempt;
|
|
385
|
+
private serveStaleOrUnconfigured;
|
|
386
|
+
}
|
|
49
387
|
export interface WriteNpmrcOptions {
|
|
50
388
|
/**
|
|
51
389
|
* Scope prefixes (e.g. `@superblocksteam`) whose existing
|
|
52
|
-
* `<scope>:registry=` lines must survive
|
|
53
|
-
*
|
|
390
|
+
* `<scope>:registry=` lines must survive — together with every
|
|
391
|
+
* auth-family key (`_authToken`, `_password`, `username`, `email`,
|
|
392
|
+
* `_auth`) keyed on the same `//<origin>/` prefix as
|
|
393
|
+
* the preserved registry URL. Used to keep scope mappings baked into a
|
|
394
|
+
* template `.npmrc` by setup-template.sh in EE builds, including the
|
|
395
|
+
* GHPR token that authenticates `@superblocksteam/*` installs
|
|
396
|
+
* (APPS-4300). When the same scope is also overridden in
|
|
397
|
+
* `config.scopes`, both the registry line and its auth-family lines
|
|
398
|
+
* are dropped in favour of the override.
|
|
54
399
|
*/
|
|
55
400
|
preserveScopeLines?: string[];
|
|
401
|
+
/**
|
|
402
|
+
* POSIX file mode for the written `.npmrc`. Defaults to `0o600` (owner
|
|
403
|
+
* read/write) because the per-install-site writers rewrite the file on
|
|
404
|
+
* every install; the immutability angle doesn't apply there. Callers that
|
|
405
|
+
* own a persistent file users should not clobber (e.g. the home-level
|
|
406
|
+
* writer at APPS-4231) pass `0o400` to drop the owner write bit. Atomic
|
|
407
|
+
* rename in this writer is governed by parent-dir perms, not the target
|
|
408
|
+
* file mode, so a stricter mode does not interfere with subsequent
|
|
409
|
+
* re-writes from the same caller.
|
|
410
|
+
*/
|
|
411
|
+
mode?: number;
|
|
412
|
+
/**
|
|
413
|
+
* Optional plain-text header written as the first line of the file,
|
|
414
|
+
* prefixed with `; ` so npm and `ini.parse` treat it as a comment. Used as
|
|
415
|
+
* an in-band ownership marker so a delete-on-unset path can tell a file
|
|
416
|
+
* this writer created apart from one the operator hand-maintains. Must
|
|
417
|
+
* not contain `\r` or `\n`.
|
|
418
|
+
*/
|
|
419
|
+
header?: string;
|
|
56
420
|
}
|
|
57
421
|
/**
|
|
58
422
|
* Renders the npm registry config to an `.npmrc` file at `targetPath`.
|
|
59
423
|
*
|
|
424
|
+
* Uses `ini.stringify` (the same library `@npmcli/config` uses to read and
|
|
425
|
+
* write `.npmrc`) so the file is guaranteed to round-trip through
|
|
426
|
+
* `ini.parse`. This handles value-quoting for `=`, `\r`, `\n`, leading `[`,
|
|
427
|
+
* leading/trailing whitespace, and escapes `;` / `#` so they're not treated
|
|
428
|
+
* as comments.
|
|
429
|
+
*
|
|
430
|
+
* Validation NOT covered by `ini`:
|
|
431
|
+
* - `noControlChars` Zod refinement: `ini.safe` JSON-quotes `\r`/`\n`
|
|
432
|
+
* rather than rejecting them, and accepts other C0 control bytes
|
|
433
|
+
* (`\x00..\x1f`) unchanged — so we reject the entire C0 range at the
|
|
434
|
+
* wire-schema layer instead.
|
|
435
|
+
* - Scope grammar (`@scope` must match npm's regex): `@npmcli/config`
|
|
436
|
+
* does not validate scope names.
|
|
437
|
+
* - https-only registry URLs: npm itself accepts http.
|
|
438
|
+
*
|
|
60
439
|
* When `preserveScopeLines` is provided, any existing `<scope>:registry=`
|
|
61
|
-
*
|
|
440
|
+
* keys for those scopes are preserved (so EE-baked
|
|
62
441
|
* `@superblocksteam:registry=https://npm.pkg.github.com/` survives) UNLESS
|
|
63
|
-
* the same scope is explicitly overridden in `config.scopes`.
|
|
442
|
+
* the same scope is explicitly overridden in `config.scopes`. The
|
|
443
|
+
* preserved value is read via `ini.parse` from the existing file, so
|
|
444
|
+
* `ini`'s own quoting rules apply (rather than our older line-grep that
|
|
445
|
+
* could mis-handle quoted values).
|
|
64
446
|
*
|
|
65
447
|
* Idempotent: rewrites the file in full each call. Writes are atomic (tmp +
|
|
66
448
|
* rename) and the file mode is restricted to 0600 because the file may carry
|
|
67
449
|
* an auth token.
|
|
450
|
+
*
|
|
451
|
+
* Requires `config.configured === true` OR `config.allowInstallScripts === false`
|
|
452
|
+
* (so the writer can emit a policy-only `.npmrc` with just `ignore-scripts=true`
|
|
453
|
+
* even when no registry rows are configured). A scoped-only config (no `default`
|
|
454
|
+
* entry) is valid — only scope `:registry=` lines are emitted, and unscoped
|
|
455
|
+
* packages fall through to public npm. This matches the server contract
|
|
456
|
+
* (the `(org, scope)` unique constraint allows scoped-only rows) and is
|
|
457
|
+
* the right shape for customers who only want to override one `@scope`
|
|
458
|
+
* without redirecting the rest of npm.
|
|
68
459
|
*/
|
|
69
460
|
export declare function writeNpmrc(targetPath: string, config: NpmRegistryConfig, options?: WriteNpmrcOptions): Promise<void>;
|
|
70
461
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
462
|
+
* Filename of the on-disk backup of the baked-in `.npmrc` that ships with the
|
|
463
|
+
* dev-server image. Captured once per pod boot by `maybeWriteNpmrcForDir`
|
|
464
|
+
* before the first `writeNpmrc` rewrite, then used as the restore source when
|
|
465
|
+
* the org transitions back to `not-configured` (e.g. the last
|
|
466
|
+
* `org_npm_registry` row was deleted). Lives sibling to `.npmrc` in the same
|
|
467
|
+
* directory writes target.
|
|
468
|
+
*/
|
|
469
|
+
export declare const NPMRC_DEFAULT_FILENAME = ".npmrc.default";
|
|
470
|
+
/**
|
|
471
|
+
* Outcome of a `snapshotInitialNpmrc` attempt. Lets a caller decide
|
|
472
|
+
* whether a usable backup now exists before it acts on the symmetric
|
|
473
|
+
* restore path — in particular, whether it is safe to ask
|
|
474
|
+
* `restoreInitialNpmrc` to UNLINK a Superblocks-owned target when the
|
|
475
|
+
* backup turns up missing.
|
|
74
476
|
*
|
|
75
|
-
*
|
|
477
|
+
* - `created` — this call wrote the hardlink; the backup is now present
|
|
478
|
+
* and holds the baked-in baseline.
|
|
479
|
+
* - `exists` — the backup was already present (prior boot, or a
|
|
480
|
+
* concurrent caller won the race). A usable backup exists.
|
|
481
|
+
* - `no-source` — `targetPath` had no baked-in file to snapshot (ENOENT).
|
|
482
|
+
* The natural restore baseline is "no file"; there is
|
|
483
|
+
* nothing to back up and nothing to restore to.
|
|
484
|
+
* - `failed` — the snapshot was attempted against a real target but
|
|
485
|
+
* `link(2)` failed for a reason other than EEXIST/ENOENT
|
|
486
|
+
* (e.g. EXDEV when target and backup straddle filesystems).
|
|
487
|
+
* A baked-in file existed but NO backup was produced — the
|
|
488
|
+
* restore path must NOT treat a missing backup as "nothing
|
|
489
|
+
* to preserve" and unlink the target.
|
|
76
490
|
*/
|
|
77
|
-
export
|
|
491
|
+
export type SnapshotInitialNpmrcOutcome = "created" | "exists" | "no-source" | "failed";
|
|
78
492
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* `
|
|
82
|
-
* the
|
|
493
|
+
* Snapshot `targetPath` to `backupPath` exactly once if the backup does
|
|
494
|
+
* not already exist. Lets a subsequent `writeNpmrc`-style rewrite of
|
|
495
|
+
* `targetPath` happen non-destructively: a restore path has a baked-in
|
|
496
|
+
* source to copy back when the org transitions to `not-configured`.
|
|
497
|
+
*
|
|
498
|
+
* Uses `link(2)` rather than read + write so the snapshot is concurrency-
|
|
499
|
+
* safe. Two properties matter:
|
|
500
|
+
*
|
|
501
|
+
* - The kernel serializes hardlink creation: only one of N concurrent
|
|
502
|
+
* callers wins; the rest see EEXIST. No read-then-write window where
|
|
503
|
+
* a slow caller could observe a `writeNpmrc`-rewritten target and
|
|
504
|
+
* poison the backup with the private registry content.
|
|
505
|
+
* - `writeNpmrc` rewrites the target via tmp + rename, which gives it
|
|
506
|
+
* a fresh inode. The hardlink at `backupPath` keeps the original
|
|
507
|
+
* inode (with the baked-in content) alive — that's the whole point.
|
|
508
|
+
*
|
|
509
|
+
* Silently no-ops in two cases:
|
|
510
|
+
* - `backupPath` is already present (subsequent boots, or a second
|
|
511
|
+
* call in the same boot after the first capture landed). Important so
|
|
512
|
+
* a later `writeNpmrc`-rewritten target is never mistaken for the
|
|
513
|
+
* baked-in baseline.
|
|
514
|
+
* - `targetPath` does not exist (image without a baked-in `.npmrc`,
|
|
515
|
+
* or a brownfield app dir that never had one). The natural "restore"
|
|
516
|
+
* state is "no file", which the restore path handles by treating an
|
|
517
|
+
* absent backup as "no file" too — for that case `restoreInitialNpmrc`
|
|
518
|
+
* unlinks the target if asked, otherwise leaves it alone.
|
|
519
|
+
*
|
|
520
|
+
* Other errors degrade to a warning + no-op rather than throwing — the
|
|
521
|
+
* capture is a best-effort safety net for the restore path, not a
|
|
522
|
+
* precondition for the install path itself.
|
|
523
|
+
*
|
|
524
|
+
* Returns a `SnapshotInitialNpmrcOutcome` so a caller can tell whether a
|
|
525
|
+
* usable backup now exists. This matters for the destructive restore path:
|
|
526
|
+
* a silent `failed` (e.g. EXDEV) leaves no backup behind, so a later
|
|
527
|
+
* `not-configured` transition must NOT mistake the absent backup for
|
|
528
|
+
* "nothing to preserve" and unlink a real baked-in userconfig (APPS-4428).
|
|
529
|
+
* Still never throws — the outcome is advisory, not an error channel.
|
|
530
|
+
*
|
|
531
|
+
* Shared with the home-npmrc writer (CLI startup, target =
|
|
532
|
+
* `~/.superblocks/npmrc`) so both project-dir and home flows agree on the
|
|
533
|
+
* snapshot/restore semantics.
|
|
534
|
+
*/
|
|
535
|
+
export declare function snapshotInitialNpmrc(targetPath: string, backupPath: string): Promise<SnapshotInitialNpmrcOutcome>;
|
|
536
|
+
export interface RestoreInitialNpmrcOptions {
|
|
537
|
+
/**
|
|
538
|
+
* When `true`, missing backup AND a present target file means "remove
|
|
539
|
+
* the target": the caller owns the target file and has no image-baked
|
|
540
|
+
* baseline to fall back to, so leaving a stale rewrite in place would
|
|
541
|
+
* be wrong. The home-npmrc writer (`~/.superblocks/npmrc`) passes this
|
|
542
|
+
* because the file is Superblocks-owned — nothing else should be
|
|
543
|
+
* reading from it, and leaving a stale configured-org registry/auth
|
|
544
|
+
* after a transition to `not-configured` is the exact case
|
|
545
|
+
* `gpoulios-sb` flagged on APPS-4328.
|
|
546
|
+
*
|
|
547
|
+
* When `false` (the default), missing backup means "leave the target
|
|
548
|
+
* alone": the caller (project `.npmrc`) shares the file with template
|
|
549
|
+
* tooling and lockfile-aware installs; an empty or absent file would
|
|
550
|
+
* break unrelated callers. This is the original APPS-4320 semantics.
|
|
551
|
+
*/
|
|
552
|
+
unlinkTargetWhenBackupMissing?: boolean;
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Restore `targetPath` from `backupPath` when the org has transitioned
|
|
556
|
+
* back to `not-configured` (e.g. last `org_npm_registry` row deleted).
|
|
557
|
+
* Without this, a file previously rewritten by `writeNpmrc` stays in
|
|
558
|
+
* place pointing at a registry the customer just removed — the exact
|
|
559
|
+
* case APPS-4320 closes for project `.npmrc`, and APPS-4328 closes for
|
|
560
|
+
* the home-level userconfig.
|
|
561
|
+
*
|
|
562
|
+
* Best-effort, never throws. The project-dir caller
|
|
563
|
+
* (`maybeWriteNpmrcForDir` → `prepareForPrivateRegistry`) needs to fall
|
|
564
|
+
* through to `stripResolvedFromLockfile` even when the restore can't
|
|
565
|
+
* run; the home-level caller (`syncHomeNpmrc`) needs to finish dev-server
|
|
566
|
+
* startup. Any error here degrades to a warn + no-op so the surrounding
|
|
567
|
+
* install path stays alive.
|
|
568
|
+
*
|
|
569
|
+
* Skips the rewrite (without a warning) in three harmless cases:
|
|
570
|
+
* - `targetPath` does not exist. The baked-in baseline for this dir is
|
|
571
|
+
* "no file"; there is nothing to restore to.
|
|
572
|
+
* - `backupPath` is missing AND `options.unlinkTargetWhenBackupMissing`
|
|
573
|
+
* is not set. Expected on pods that never had `org_npm_registry`
|
|
574
|
+
* configured (snapshot is gated on the configured branch), AND on
|
|
575
|
+
* older pods whose target was rewritten before this commit landed.
|
|
576
|
+
* In both cases the running file is what the pod has lived with —
|
|
577
|
+
* leave it alone.
|
|
578
|
+
* - `targetPath` already byte-matches `backupPath`. Avoids a no-op
|
|
579
|
+
* rewrite that would bump mtime for downstream watchers (e.g. Tilt /
|
|
580
|
+
* Vite file-sync).
|
|
581
|
+
*
|
|
582
|
+
* When `options.unlinkTargetWhenBackupMissing` is true and the backup is
|
|
583
|
+
* absent but the target exists, the target is unlinked — see the option
|
|
584
|
+
* comment.
|
|
585
|
+
*/
|
|
586
|
+
export declare function restoreInitialNpmrc(targetPath: string, backupPath: string, options?: RestoreInitialNpmrcOptions): Promise<void>;
|
|
587
|
+
/**
|
|
588
|
+
* Outcome of `ensureNpmrcGitignored`. The caller's fail-closed decision is
|
|
589
|
+
* `!ignored`: any state in which we cannot positively guarantee that
|
|
590
|
+
* `.npmrc` is ignored from `<dir>` — whether `.git` exists today or not —
|
|
591
|
+
* blocks the credential write. `hasGit` is retained for logging /
|
|
592
|
+
* diagnostics so warnings can distinguish the "native git can stage on the
|
|
593
|
+
* next commit" case from the "no native git today, but a future `git init`
|
|
594
|
+
* would stage" case.
|
|
595
|
+
*/
|
|
596
|
+
export interface EnsureNpmrcGitignoredResult {
|
|
597
|
+
/**
|
|
598
|
+
* True iff `.npmrc` is now positively known to be ignored from `<dir>`.
|
|
599
|
+
* The bar depends on whether a `.git` is present:
|
|
600
|
+
*
|
|
601
|
+
* - Native git (`<dir>/.git` exists): an ignore entry was written
|
|
602
|
+
* (`<dir>/.gitignore` or the per-clone `<dir>/.git/info/exclude`) AND
|
|
603
|
+
* `git check-ignore .npmrc` confirms the file is effectively ignored
|
|
604
|
+
* (catches later `!.npmrc` negations) AND `git ls-files .npmrc` shows
|
|
605
|
+
* the file is not already tracked (an ignore line does not protect a
|
|
606
|
+
* file already in the index).
|
|
607
|
+
*
|
|
608
|
+
* - Non-native (no `<dir>/.git`): `<dir>/.gitignore` was appended to
|
|
609
|
+
* OR created with the `.npmrc` line. We create `.gitignore` even
|
|
610
|
+
* when none exists so a subsequent `git init` in the same dir is
|
|
611
|
+
* future-safe: a customer who later turns on native git for an app
|
|
612
|
+
* where a credential-bearing `.npmrc` already sits on disk would
|
|
613
|
+
* otherwise stage the token on their first `git add .` before any
|
|
614
|
+
* install path re-runs this helper. Returns `false` only when the
|
|
615
|
+
* `.gitignore` write itself fails (rare — disk full, permission
|
|
616
|
+
* denied, `.gitignore` is a directory); in that case the caller MUST
|
|
617
|
+
* refuse to write the credential-bearing `.npmrc`, because the
|
|
618
|
+
* future-git leak path the reviewer flagged is still open (a later
|
|
619
|
+
* `git init` finds the token on disk with no ignore rule).
|
|
620
|
+
*/
|
|
621
|
+
ignored: boolean;
|
|
622
|
+
/** True iff `<dir>` is inside any git working tree — either because
|
|
623
|
+
* `<dir>/.git` exists OR because a parent directory has `.git` (nested-repo
|
|
624
|
+
* layout). Diagnostic only — the fail-closed decision in
|
|
625
|
+
* `maybeWriteNpmrcForDir` is `!ignored`, regardless of `hasGit`. The
|
|
626
|
+
* nested-repo case matters because a parent's `git add .` will stage
|
|
627
|
+
* `<dir>/.npmrc` unless an ignore rule excludes it; see PR #19642 review
|
|
628
|
+
* from cursor[bot]. */
|
|
629
|
+
hasGit: boolean;
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Ensure `.npmrc` is git-ignored from `<dir>` before any credential-bearing
|
|
633
|
+
* `.npmrc` is written.
|
|
634
|
+
*
|
|
635
|
+
* Why this matters: `maybeWriteNpmrcForDir` writes a `.npmrc` containing
|
|
636
|
+
* `//host/:_authToken=<customer token>` at the app root. The DBFS sync
|
|
637
|
+
* already excludes `.npmrc` from upload (`codeModeExcludedFiles` in
|
|
638
|
+
* `file-system-helpers.ts`), but the native-git path calls `git.add(".")`
|
|
639
|
+
* (socket-manager `gitCommitLocal`/`gitPull`, agent `git`/`git_raw` tools)
|
|
640
|
+
* which stages everything not listed in the app's on-disk ignore. Without
|
|
641
|
+
* this enforcement, a customer with a configured private registry pushes
|
|
642
|
+
* their `_authToken` to their external git remote on the next commit. The
|
|
643
|
+
* template `.gitignore` covers new apps; this helper covers the existing
|
|
644
|
+
* fleet whose `.gitignore` predates the registry feature.
|
|
645
|
+
*
|
|
646
|
+
* Behaviour, in three layers:
|
|
647
|
+
*
|
|
648
|
+
* 1. Non-native-git (`<dir>/.git` does not exist):
|
|
649
|
+
* - Append `.npmrc` to `<dir>/.gitignore`, or create the file if
|
|
650
|
+
* it doesn't exist. We create `.gitignore` here (not just when
|
|
651
|
+
* `.git` already exists) so a subsequent `git init` in the same
|
|
652
|
+
* directory is future-safe: a customer who later turns on native
|
|
653
|
+
* git for an app where a credential-bearing `.npmrc` already
|
|
654
|
+
* sits on disk would otherwise stage the token on their first
|
|
655
|
+
* `git add .` before any install path re-runs this helper.
|
|
656
|
+
* - On success return `{ ignored: true, hasGit: false }`. On a
|
|
657
|
+
* read or write failure (`.gitignore` is a directory, disk full,
|
|
658
|
+
* permission denied) return `{ ignored: false, hasGit: false }`.
|
|
659
|
+
* The caller MUST refuse to write the credential-bearing
|
|
660
|
+
* `.npmrc` in that case: even though no native git checkout
|
|
661
|
+
* exists today, a later `git init` (or wiring this dir into an
|
|
662
|
+
* existing repo) would find the on-disk token and stage it on
|
|
663
|
+
* the first `git add .` — exactly the future-git leak path
|
|
664
|
+
* gpoulios-sb flagged in code review.
|
|
665
|
+
*
|
|
666
|
+
* 2. Native-git (`<dir>/.git` exists), `.gitignore` path:
|
|
667
|
+
* - Read or create `.gitignore`, append `.npmrc` if missing. After
|
|
668
|
+
* the append, verify with git itself (`verifyNpmrcIgnoredByGit`)
|
|
669
|
+
* that the file is effectively ignored AND not already tracked.
|
|
670
|
+
* Only then return `ignored: true`.
|
|
671
|
+
*
|
|
672
|
+
* 3. Native-git, `.git/info/exclude` fallback:
|
|
673
|
+
* - Only attempted when the `.gitignore` write failed AND `.git` is a
|
|
674
|
+
* directory (regular repo). `.git/info/exclude` is the per-clone
|
|
675
|
+
* ignore file: not synced to remotes, but exactly as effective as
|
|
676
|
+
* `.gitignore` at preventing `git add` from staging the file. The
|
|
677
|
+
* fallback lets us still fail-closed when the working tree is
|
|
678
|
+
* read-only but the local clone metadata is writable. After the
|
|
679
|
+
* exclude append, the same `verifyNpmrcIgnoredByGit` check runs.
|
|
680
|
+
*
|
|
681
|
+
* Why git verification, not just text: a `.gitignore` containing `.npmrc`
|
|
682
|
+
* is necessary but not sufficient. Two real leak paths bypass a naive
|
|
683
|
+
* "any line matches" textual check:
|
|
684
|
+
* - A later `!.npmrc` re-includes the file (gitignore is order-sensitive).
|
|
685
|
+
* `textIgnoresNpmrc` is already negation-aware (returns true only when
|
|
686
|
+
* the LAST matching rule is positive), so for this case the textual
|
|
687
|
+
* check correctly reports "not ignored" and `appendNpmrcIgnore` writes
|
|
688
|
+
* a fresh positive `.npmrc` line that becomes the new last-match.
|
|
689
|
+
* This is the gpoulios-sb PR #19642 re-review "always append" remedy,
|
|
690
|
+
* applied uniformly to both branches (non-native-git relies on it as
|
|
691
|
+
* the authoritative check; native-git double-checks with git below).
|
|
692
|
+
* - An already-tracked `.npmrc` stages on every commit regardless of
|
|
693
|
+
* ignore rules. No textual check sees the index, so for native-git
|
|
694
|
+
* `git ls-files --error-unmatch` is the only catch.
|
|
695
|
+
*
|
|
696
|
+
* Returns `{ ignored, hasGit }`. The caller's fail-closed signal is
|
|
697
|
+
* `ignored === false` regardless of `hasGit`: any state in which we cannot
|
|
698
|
+
* guarantee `.npmrc` is ignored from `<dir>` blocks the credential write,
|
|
699
|
+
* because either the current native git checkout would stage the token on
|
|
700
|
+
* the next `git add .`, or a future `git init` in the same dir would find
|
|
701
|
+
* the token on disk and stage it on the first `git add .`. `hasGit` is
|
|
702
|
+
* retained for logging only — it lets the warning distinguish the
|
|
703
|
+
* "tomorrow's risk" case from the "today's risk" case.
|
|
704
|
+
*/
|
|
705
|
+
export declare function ensureNpmrcGitignored(dir: string): Promise<EnsureNpmrcGitignoredResult>;
|
|
706
|
+
/**
|
|
707
|
+
* Convenience: invoke `writeNpmrc` against `<dir>/.npmrc` when the client
|
|
708
|
+
* resolves to a configured (or stale) registry config. No-op when:
|
|
709
|
+
*
|
|
710
|
+
* - `client` is undefined (test-only opt-out — production code paths
|
|
711
|
+
* always pass a client constructed by AiService); or
|
|
712
|
+
* - the resolved config is `source: "unreachable"` (transient cold-cache
|
|
713
|
+
* outage — we leave `.npmrc` whatever it currently is and reconcile on
|
|
714
|
+
* the next successful fetch, rather than clobbering a last-known-good
|
|
715
|
+
* private-registry `.npmrc` back to baseline during the outage window);
|
|
716
|
+
* or
|
|
717
|
+
* - the resolved config is `source: "not-configured"` (deliberate unset
|
|
718
|
+
* observation). If a previously-written `.npmrc` exists that no longer
|
|
719
|
+
* matches the baked-in `.npmrc.default`, restore it — see APPS-4320.
|
|
720
|
+
*
|
|
721
|
+
* On the first call per pod boot for `<dir>`, captures `<dir>/.npmrc` to
|
|
722
|
+
* `<dir>/.npmrc.default` before any rewrite so the restore path above has
|
|
723
|
+
* a source to copy back from.
|
|
724
|
+
*
|
|
725
|
+
* Returns the resolved fetch result so callers can branch on `source` for
|
|
726
|
+
* observability, or `undefined` when no client was provided.
|
|
727
|
+
*/
|
|
728
|
+
export declare function maybeWriteNpmrcForDir(dir: string, options?: WriteNpmrcOptions, client?: NpmRegistryClient): Promise<NpmRegistryFetchResult | undefined>;
|
|
729
|
+
/**
|
|
730
|
+
* Materializes the private-registry `.npmrc` AND unconditionally strips
|
|
731
|
+
* `resolved` URLs from any lockfile present in `dir`, so a subsequent
|
|
732
|
+
* `npm install` is guaranteed to re-resolve through the active registry.
|
|
733
|
+
* The `.npmrc` write is gated on whether the client resolves to a configured
|
|
734
|
+
* registry; the lockfile strip runs regardless.
|
|
83
735
|
*
|
|
84
736
|
* Why the strip is unconditional (decoupled from the `.npmrc` write):
|
|
85
|
-
* - SaaS dev-server pods (staging/prod) run without
|
|
86
|
-
*
|
|
87
|
-
* `resolved` URLs via DBFS state (APPS-4300). Gating
|
|
88
|
-
*
|
|
89
|
-
*
|
|
737
|
+
* - SaaS dev-server pods (staging/prod) often run without a configured
|
|
738
|
+
* org npm registry, but their lockfiles can still be poisoned with
|
|
739
|
+
* cross-registry `resolved` URLs via DBFS state (APPS-4300). Gating
|
|
740
|
+
* the strip on the client's configured-ness meant the only safety net
|
|
741
|
+
* never fired in the exact environment where it mattered. Always
|
|
742
|
+
* stripping closes that read path.
|
|
90
743
|
* - The mutation is transient: `npm install` rewrites `resolved` with
|
|
91
744
|
* URLs from the active `.npmrc` registry on the very next line, so a
|
|
92
745
|
* local dev whose lockfile pointed at npmjs.org sees the same URLs
|
|
@@ -102,10 +755,11 @@ export declare function maybeWriteNpmrcForDir(dir: string, options?: WriteNpmrcO
|
|
|
102
755
|
* (only configure GHPR scope for ephemeral builds) is the actual durable
|
|
103
756
|
* fix; this strip is the runtime safety net for already-poisoned DBFS state.
|
|
104
757
|
*
|
|
105
|
-
* Returns the
|
|
106
|
-
* `
|
|
758
|
+
* Returns the resolved fetch result when a client is provided (so callers
|
|
759
|
+
* can branch on `source` for observability), or `undefined` when no client
|
|
760
|
+
* was provided. The lockfile strip happens in both cases.
|
|
107
761
|
*/
|
|
108
|
-
export declare function prepareForPrivateRegistry(dir: string, options?: WriteNpmrcOptions,
|
|
762
|
+
export declare function prepareForPrivateRegistry(dir: string, options?: WriteNpmrcOptions, client?: NpmRegistryClient): Promise<NpmRegistryFetchResult | undefined>;
|
|
109
763
|
/**
|
|
110
764
|
* Removes the `resolved` field from every entry in `.packages` of an npm v2+
|
|
111
765
|
* lockfile. TS-side counterpart to `scripts/strip-lockfile-resolved.sh`.
|
|
@@ -134,4 +788,38 @@ export declare function prepareForPrivateRegistry(dir: string, options?: WriteNp
|
|
|
134
788
|
* crash mid-write.
|
|
135
789
|
*/
|
|
136
790
|
export declare function stripResolvedFromLockfile(dir: string): Promise<void>;
|
|
791
|
+
export declare function stripResolvedFromLockfilePath(lockfilePath: string): Promise<void>;
|
|
792
|
+
/**
|
|
793
|
+
* APPS-4370. Build a disk-backed `LastKnownRegistryPolicyStore` rooted at
|
|
794
|
+
* `<rootDir>/.superblocks/orgs/<orgId>/.registry-was-configured`.
|
|
795
|
+
*
|
|
796
|
+
* The marker's PRESENCE is the semantic signal; its content is informal
|
|
797
|
+
* (an ISO timestamp for forensics — "when was this org first seen with a
|
|
798
|
+
* configured registry"). Writes are best-effort: a write failure (EACCES
|
|
799
|
+
* on a 0o500 parent, ENOSPC) is logged and swallowed. Reads return false
|
|
800
|
+
* on any error so a transient IO problem doesn't degrade today's
|
|
801
|
+
* "proceed" behaviour into a fail-closed install.
|
|
802
|
+
*
|
|
803
|
+
* APPS-4427: `markConfigured` is AWAITED by its caller
|
|
804
|
+
* (`NpmRegistryClient.markPolicyConfigured`) before a `configured` / `stale`
|
|
805
|
+
* resolution is handed back, so the marker is durably on disk before that
|
|
806
|
+
* result is used — closing the crash window an un-awaited write would leave
|
|
807
|
+
* open. The write stays async (`fs/promises`, per the ai-service no-sync-fs
|
|
808
|
+
* rule) and is guarded to run at most once per process, so awaiting it stays
|
|
809
|
+
* off the install hot path after the first configured resolution.
|
|
810
|
+
*
|
|
811
|
+
* The `rootDir` is injected (rather than hard-coded to `os.homedir()`)
|
|
812
|
+
* so tests can isolate to a tmp directory and so the dev-server can
|
|
813
|
+
* point the store at the same disk it already manages
|
|
814
|
+
* (`~/.superblocks/...`). The per-org path keeps multiple orgs running
|
|
815
|
+
* against the same machine from contaminating each other's marker state.
|
|
816
|
+
*/
|
|
817
|
+
export declare function createDiskRegistryPolicyStore(opts: {
|
|
818
|
+
organizationId: string;
|
|
819
|
+
rootDir: string;
|
|
820
|
+
}): LastKnownRegistryPolicyStore;
|
|
821
|
+
export { parseNpmJsonError, parseNpmJsonDiagnostic, classifyNpmExecStderr, } from "./npm-error-parser.js";
|
|
822
|
+
export type { ParseContext } from "./npm-error-parser.js";
|
|
823
|
+
export { NpmInstallBlocked, NpmInstallError, scrubSecrets } from "../types.js";
|
|
824
|
+
export type { NpmInstallBlockedReason, NpmInstallBlockedSubreason, NpmInstallBlockedDetails, } from "../types.js";
|
|
137
825
|
//# sourceMappingURL=npm-registry.d.ts.map
|