@fgv/ts-extras 5.1.0-45 → 5.1.0-46
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/packlets/ai-assist/index.js +1 -1
- package/dist/packlets/ai-assist/index.js.map +1 -1
- package/dist/packlets/ai-assist/jsonResponse.js +270 -7
- package/dist/packlets/ai-assist/jsonResponse.js.map +1 -1
- package/dist/packlets/ai-assist/model.js +14 -0
- package/dist/packlets/ai-assist/model.js.map +1 -1
- package/dist/packlets/ai-assist/registry.js +57 -14
- package/dist/packlets/ai-assist/registry.js.map +1 -1
- package/dist/packlets/zip-file-tree/zipFileTreeAccessors.js +65 -7
- package/dist/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -1
- package/dist/packlets/zip-file-tree/zipFileTreeWriter.js +16 -1
- package/dist/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -1
- package/dist/ts-extras.d.ts +253 -13
- package/lib/packlets/ai-assist/index.d.ts +1 -1
- package/lib/packlets/ai-assist/index.d.ts.map +1 -1
- package/lib/packlets/ai-assist/index.js +3 -2
- package/lib/packlets/ai-assist/index.js.map +1 -1
- package/lib/packlets/ai-assist/jsonResponse.d.ts +96 -0
- package/lib/packlets/ai-assist/jsonResponse.d.ts.map +1 -1
- package/lib/packlets/ai-assist/jsonResponse.js +271 -7
- package/lib/packlets/ai-assist/jsonResponse.js.map +1 -1
- package/lib/packlets/ai-assist/model.d.ts +43 -0
- package/lib/packlets/ai-assist/model.d.ts.map +1 -1
- package/lib/packlets/ai-assist/model.js +14 -0
- package/lib/packlets/ai-assist/model.js.map +1 -1
- package/lib/packlets/ai-assist/registry.d.ts +26 -6
- package/lib/packlets/ai-assist/registry.d.ts.map +1 -1
- package/lib/packlets/ai-assist/registry.js +57 -14
- package/lib/packlets/ai-assist/registry.js.map +1 -1
- package/lib/packlets/zip-file-tree/zipFileTreeAccessors.d.ts +54 -6
- package/lib/packlets/zip-file-tree/zipFileTreeAccessors.d.ts.map +1 -1
- package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js +65 -7
- package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -1
- package/lib/packlets/zip-file-tree/zipFileTreeWriter.d.ts +26 -1
- package/lib/packlets/zip-file-tree/zipFileTreeWriter.d.ts.map +1 -1
- package/lib/packlets/zip-file-tree/zipFileTreeWriter.js +17 -1
- package/lib/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/registry.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n/**\n * Centralized provider registry — single source of truth for all AI provider metadata.\n * @packageDocumentation\n */\n\nimport { fail, Result, succeed } from '@fgv/ts-utils';\n\nimport {\n type AiProviderId,\n type IAiEmbeddingModelCapability,\n type IAiImageModelCapability,\n type IAiModelCapabilityConfig,\n type IAiProviderDescriptor\n} from './model';\n\n// ============================================================================\n// Built-in providers\n// ============================================================================\n\n/**\n * All known AI provider descriptors. Copy-paste first, then alphabetical.\n * @internal\n */\nconst BUILTIN_PROVIDERS: ReadonlyArray<IAiProviderDescriptor> = [\n {\n id: 'copy-paste',\n label: 'Copy / Paste',\n buttonLabel: 'AI Assist | Copy',\n needsSecret: false,\n apiFormat: 'openai',\n baseUrl: '',\n defaultModel: '',\n supportedTools: [],\n corsRestricted: false,\n streamingCorsRestricted: false,\n acceptsImageInput: false,\n thinkingMode: 'unsupported'\n },\n {\n id: 'anthropic',\n label: 'Anthropic Claude',\n buttonLabel: 'AI Assist | Claude',\n needsSecret: true,\n apiFormat: 'anthropic',\n baseUrl: 'https://api.anthropic.com/v1',\n defaultModel: {\n base: '@anthropic:sonnet', // claude-sonnet-5 (was 'claude-sonnet-4-5-20250929')\n advanced: '@anthropic:opus' // claude-opus-5\n // no frontier key → a frontier request cascades advanced → opus (see resolveModel)\n },\n aliases: {\n '@anthropic:sonnet': 'claude-sonnet-5', // base tier\n '@anthropic:opus': 'claude-opus-5', // advanced tier (was claude-opus-4-8; opus-5 is the drop-in successor at the same price)\n '@anthropic:haiku': 'claude-haiku-4-5-20251001', // NON-tier alias; modelOverride only\n '@anthropic:fable': 'claude-fable-5' // NON-tier alias; modelOverride only\n // NOTE: no thinking/image/embedding keys — Anthropic completions are all text; base\n // (sonnet-5) and advanced (opus-5) are both thinking-capable, so a thinking-context\n // call flat-falls to base safely.\n },\n supportedTools: ['web_search'],\n corsRestricted: false,\n streamingCorsRestricted: false,\n acceptsImageInput: true,\n thinkingMode: 'optional',\n // Claude 5 family requires the adaptive thinking wire shape (thinking.type: 'adaptive' +\n // output_config.effort) and 400s on the legacy thinking.type: 'enabled' + budget_tokens\n // shape; see AiAssist.isAdaptiveThinkingModel.\n adaptiveThinkingModelPrefixes: ['claude-sonnet-5', 'claude-opus-5', 'claude-fable-5']\n },\n {\n id: 'google-gemini',\n label: 'Google Gemini',\n buttonLabel: 'AI Assist | Gemini',\n needsSecret: true,\n apiFormat: 'gemini',\n baseUrl: 'https://generativelanguage.googleapis.com/v1beta',\n defaultModel: {\n base: '@google-gemini:flash',\n advanced: '@google-gemini:pro', // reuses the existing @google-gemini:pro alias (no new alias entry)\n image: '@google-gemini:flash-image',\n embedding: '@google-gemini:embedding'\n // no frontier key → a frontier request cascades advanced → pro (see resolveModel)\n },\n aliases: {\n // NOTE: the base flash line is at 3.5 while pro / flash-lite / flash-image are at 3.1 — this is\n // NOT a typo. The targets come verbatim from Google's official deprecation table: the flash base\n // line advanced to 3.5 while the other roles are on the 3.1 generation. The per-role version\n // split is exactly why the alias layer exists — consumers never see these numbers.\n '@google-gemini:flash': 'gemini-3.5-flash', // base (was gemini-2.5-flash, shutdown 2026-10-16)\n '@google-gemini:pro': 'gemini-3.1-pro-preview', // advanced-tier role (wired to the 'advanced' defaultModel key); also the frontier cascade target (was gemini-2.5-pro, 2026-10-16)\n '@google-gemini:flash-lite': 'gemini-3.1-flash-lite', // cheaper thinking-capable line; available via modelOverride only (was gemini-2.5-flash-lite, 2026-10-16)\n '@google-gemini:flash-image': 'gemini-3.1-flash-image', // image (GA id; was gemini-3.1-flash-image-preview, retired 2026-06-25)\n '@google-gemini:embedding': 'gemini-embedding-001' // NOT deprecated — aliased for uniformity only\n },\n supportedTools: ['web_search'],\n corsRestricted: false,\n streamingCorsRestricted: false,\n acceptsImageInput: true,\n thinkingMode: 'optional',\n embedding: [\n {\n modelPrefix: '',\n format: 'gemini-embeddings',\n supportsDimensions: true,\n supportsTaskType: true,\n defaultDimensions: 3072\n }\n ],\n imageGeneration: [\n {\n // Gemini Flash Image: chat-style generateContent\n modelPrefix: '',\n format: 'gemini-image-out',\n acceptsImageReferenceInput: true,\n supportsQualityParam: false,\n maxCount: 1,\n outputParamStyle: 'none',\n defaultOutputMimeType: 'image/jpeg'\n }\n ]\n },\n {\n id: 'groq',\n label: 'Groq',\n buttonLabel: 'AI Assist | Groq',\n needsSecret: true,\n apiFormat: 'openai',\n baseUrl: 'https://api.groq.com/openai/v1',\n defaultModel: 'llama-3.3-70b-versatile',\n supportedTools: [],\n corsRestricted: false,\n streamingCorsRestricted: false,\n acceptsImageInput: false,\n thinkingMode: 'unsupported'\n },\n {\n id: 'mistral',\n label: 'Mistral',\n buttonLabel: 'AI Assist | Mistral',\n needsSecret: true,\n apiFormat: 'openai',\n baseUrl: 'https://api.mistral.ai/v1',\n defaultModel: { base: 'mistral-large-latest', embedding: 'mistral-embed' },\n supportedTools: [],\n corsRestricted: false,\n streamingCorsRestricted: false,\n acceptsImageInput: false,\n thinkingMode: 'unsupported',\n embedding: [{ modelPrefix: '', format: 'openai-embeddings' }]\n },\n {\n id: 'ollama',\n label: 'Ollama (self-hosted)',\n buttonLabel: 'AI Assist | Ollama',\n needsSecret: false,\n apiFormat: 'openai',\n baseUrl: 'http://localhost:11434/v1',\n defaultModel: '',\n supportedTools: [],\n corsRestricted: false,\n streamingCorsRestricted: false,\n acceptsImageInput: false,\n thinkingMode: 'unsupported',\n embedding: [{ modelPrefix: '', format: 'openai-embeddings' }]\n },\n {\n id: 'openai',\n label: 'OpenAI',\n buttonLabel: 'AI Assist | OpenAI',\n needsSecret: true,\n apiFormat: 'openai',\n baseUrl: 'https://api.openai.com/v1',\n defaultModel: {\n base: '@openai:mini', // gpt-5.6-luna (was gpt-5.4-mini; before that 'gpt-4o' — EOL-behind)\n advanced: '@openai:flagship', // gpt-5.6-terra\n // The gpt-5.6 family works on BOTH Chat Completions and the Responses API, so the\n // frontier tier no longer needs Responses-only routing. gpt-5.5-pro (the previous\n // frontier target) remains Responses-API-only and reachable via modelOverride; the\n // `responsesOnlyModelPrefixes` marker below still routes it correctly.\n frontier: '@openai:pro', // gpt-5.6-sol\n image: '@openai:image', // gpt-image-2 (was gpt-image-1.5; before that 'dall-e-3' — EOL 2026-05-12)\n embedding: '@openai:embedding' // text-embedding-3-small (unchanged, aliased for uniformity)\n },\n aliases: {\n '@openai:mini': 'gpt-5.6-luna', // base tier (was gpt-5.4-mini)\n '@openai:flagship': 'gpt-5.6-terra', // advanced tier (was gpt-5.5)\n '@openai:pro': 'gpt-5.6-sol', // frontier tier (was gpt-5.5-pro, which was Responses-API-only; 5.6 works on chat completions)\n '@openai:nano': 'gpt-5.4-nano', // NON-tier alias; modelOverride only\n '@openai:image': 'gpt-image-2', // image (matches the gpt-image- capability prefix; was gpt-image-1.5)\n '@openai:embedding': 'text-embedding-3-small' // NOT deprecated — aliased for uniformity\n // NOTE: gpt-5.1 deliberately absent — retired March 2026.\n },\n supportedTools: ['web_search'],\n corsRestricted: false,\n streamingCorsRestricted: false,\n acceptsImageInput: true,\n thinkingMode: 'optional',\n responsesOnlyModelPrefixes: ['gpt-5.5-pro'],\n embedding: [\n {\n modelPrefix: 'text-embedding-3',\n format: 'openai-embeddings',\n supportsDimensions: true,\n maxBatchSize: 2048\n },\n {\n modelPrefix: '',\n format: 'openai-embeddings'\n }\n ],\n imageGeneration: [\n {\n modelPrefix: 'gpt-image-',\n format: 'openai-images',\n acceptsImageReferenceInput: true,\n acceptedSizes: ['1024x1024', '1536x1024', '1024x1536', 'auto'],\n supportsQualityParam: true,\n acceptedQualities: ['low', 'medium', 'high', 'auto'],\n maxCount: 10,\n outputParamStyle: 'output-format',\n defaultOutputMimeType: 'image/png'\n },\n {\n modelPrefix: '',\n format: 'openai-images',\n outputParamStyle: 'response-format',\n defaultOutputMimeType: 'image/png'\n }\n ]\n },\n {\n id: 'openai-compat',\n label: 'OpenAI-compatible (self-hosted)',\n buttonLabel: 'AI Assist | OpenAI-compat',\n needsSecret: false,\n apiFormat: 'openai',\n baseUrl: '',\n defaultModel: '',\n supportedTools: [],\n corsRestricted: false,\n streamingCorsRestricted: false,\n acceptsImageInput: false,\n thinkingMode: 'unsupported',\n embedding: [{ modelPrefix: '', format: 'openai-embeddings' }]\n },\n {\n id: 'xai-grok',\n label: 'xAI Grok',\n buttonLabel: 'AI Assist | Grok',\n needsSecret: true,\n apiFormat: 'openai',\n baseUrl: 'https://api.x.ai/v1',\n defaultModel: {\n base: '@xai-grok:standard', // grok-4.3 (was the raw id; the cheap line + retirement-wave redirect target)\n advanced: '@xai-grok:flagship', // grok-4.5 (flagship since 2026-07-08; $2/$6 sits in the advanced band)\n image: '@xai-grok:imagine' // grok-imagine-image-quality (was the raw id)\n // no frontier key → a frontier request cascades advanced → grok-4.5 (see resolveModel)\n },\n aliases: {\n '@xai-grok:standard': 'grok-4.3', // base tier; NOT deprecated — superseded as flagship by grok-4.5\n '@xai-grok:flagship': 'grok-4.5', // advanced tier; configurable reasoning effort (default high)\n '@xai-grok:imagine': 'grok-imagine-image-quality' // image tier; current (redirect target for the retired -pro)\n },\n supportedTools: ['web_search'],\n corsRestricted: true,\n streamingCorsRestricted: true,\n acceptsImageInput: true,\n thinkingMode: 'optional',\n imageGeneration: [\n {\n // grok-imagine models use JSON edits with image_url objects (different wire format)\n modelPrefix: 'grok-imagine-',\n format: 'xai-images-edits',\n acceptsImageReferenceInput: true,\n supportsQualityParam: false,\n maxCount: 10,\n outputParamStyle: 'response-format',\n defaultOutputMimeType: 'image/jpeg'\n },\n {\n // catch-all for other xai image models\n modelPrefix: '',\n format: 'xai-images',\n acceptsImageReferenceInput: false,\n supportsQualityParam: false,\n maxCount: 10,\n outputParamStyle: 'response-format',\n defaultOutputMimeType: 'image/jpeg'\n }\n ]\n }\n];\n\n/**\n * Index for O(1) lookup by id.\n * @internal\n */\nconst PROVIDER_BY_ID: ReadonlyMap<string, IAiProviderDescriptor> = new Map(\n BUILTIN_PROVIDERS.map((d) => [d.id, d])\n);\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * All valid provider ID values, in the same order as the registry.\n * @public\n */\nexport const allProviderIds: ReadonlyArray<AiProviderId> = BUILTIN_PROVIDERS.map((d) => d.id);\n\n/**\n * Get all known provider descriptors. Copy-paste first, then alphabetical.\n * @returns All built-in provider descriptors\n * @public\n */\nexport function getProviderDescriptors(): ReadonlyArray<IAiProviderDescriptor> {\n return BUILTIN_PROVIDERS;\n}\n\n/**\n * Get a provider descriptor by id.\n * @param id - The provider identifier\n * @returns The descriptor, or a failure if the provider is unknown\n * @public\n */\nexport function getProviderDescriptor(id: string): Result<IAiProviderDescriptor> {\n const descriptor = PROVIDER_BY_ID.get(id);\n if (!descriptor) {\n return fail(`unknown AI provider: ${id}`);\n }\n return succeed(descriptor);\n}\n\n/**\n * Whether a provider declares any image-generation capability at all.\n *\n * @param descriptor - The provider descriptor\n * @returns `true` when {@link IAiProviderDescriptor.imageGeneration} has at\n * least one entry; `false` otherwise.\n * @public\n */\nexport function supportsImageGeneration(descriptor: IAiProviderDescriptor): boolean {\n return (descriptor.imageGeneration?.length ?? 0) > 0;\n}\n\n/**\n * Resolve the image-generation capability that applies to a given model id\n * for a provider. Returns the entry from\n * {@link IAiProviderDescriptor.imageGeneration} whose `modelPrefix` is the\n * longest prefix of `modelId`. Ties are broken by first-encountered, so rule\n * order does not matter for correctness — only for tie-breaking among rules\n * with identical-length prefixes (an unusual case).\n *\n * @param descriptor - The provider descriptor\n * @param modelId - The resolved image model id\n * @returns The matching capability, or `undefined` when no rule matches or\n * the provider declares no image-generation capabilities.\n * @public\n */\nexport function resolveImageCapability(\n descriptor: IAiProviderDescriptor,\n modelId: string\n): IAiImageModelCapability | undefined {\n return (descriptor.imageGeneration ?? [])\n .filter((cap) => modelId.startsWith(cap.modelPrefix))\n .reduce<IAiImageModelCapability | undefined>(\n (best, cap) => (best && best.modelPrefix.length >= cap.modelPrefix.length ? best : cap),\n undefined\n );\n}\n\n/**\n * Whether a provider declares any embedding capability at all.\n *\n * @param descriptor - The provider descriptor\n * @returns `true` when {@link IAiProviderDescriptor.embedding} has at least one\n * entry; `false` otherwise.\n * @public\n */\nexport function supportsEmbedding(descriptor: IAiProviderDescriptor): boolean {\n return (descriptor.embedding?.length ?? 0) > 0;\n}\n\n/**\n * Resolve the embedding capability that applies to a given model id for a\n * provider. Returns the entry from {@link IAiProviderDescriptor.embedding} whose\n * `modelPrefix` is the longest prefix of `modelId`. Ties are broken by\n * first-encountered.\n *\n * @param descriptor - The provider descriptor\n * @param modelId - The resolved embedding model id\n * @returns The matching capability, or `undefined` when no rule matches or the\n * provider declares no embedding capabilities.\n * @public\n */\nexport function resolveEmbeddingCapability(\n descriptor: IAiProviderDescriptor,\n modelId: string\n): IAiEmbeddingModelCapability | undefined {\n return (descriptor.embedding ?? [])\n .filter((cap) => modelId.startsWith(cap.modelPrefix))\n .reduce<IAiEmbeddingModelCapability | undefined>(\n (best, cap) => (best && best.modelPrefix.length >= cap.modelPrefix.length ? best : cap),\n undefined\n );\n}\n\n// ============================================================================\n// Default model capability config\n// ============================================================================\n\n/**\n * Default capability config used by `callProviderListModels` when callers\n * don't supply their own. Patterns are intentionally narrow — false\n * positives are worse than missing a model. Caller can override per call\n * via {@link IProviderListModelsParams.capabilityConfig}.\n *\n * @public\n */\nexport const DEFAULT_MODEL_CAPABILITY_CONFIG: IAiModelCapabilityConfig = {\n perProvider: {\n openai: [\n { idPattern: /^gpt-image/, capabilities: ['image-generation'] },\n { idPattern: /^text-embedding/, capabilities: ['embedding'] },\n { idPattern: /^gpt-5/, capabilities: ['chat', 'tools', 'vision', 'thinking'] },\n { idPattern: /^gpt-4/, capabilities: ['chat', 'tools', 'vision'] },\n { idPattern: /^gpt-3\\.5/, capabilities: ['chat'] },\n { idPattern: /^o\\d/, capabilities: ['chat', 'tools', 'thinking'] }\n ],\n 'xai-grok': [\n { idPattern: /-image/, capabilities: ['image-generation'] },\n // grok-4.5 needs its own rule: it would otherwise hit only /^grok-4/ and lose\n // thinking, yet it has configurable reasoning effort. Detection accumulates across\n // matching rules, so /^grok-4/ still contributes vision (same as grok-4.3).\n { idPattern: /^grok-4\\.5/, capabilities: ['chat', 'tools', 'thinking'] },\n { idPattern: /^grok-4\\.3/, capabilities: ['chat', 'tools', 'thinking'] },\n { idPattern: /^grok-4$/, capabilities: ['chat', 'tools', 'thinking'] },\n { idPattern: /^grok-4/, capabilities: ['chat', 'tools', 'vision'] },\n { idPattern: /^grok-3-mini/, capabilities: ['chat', 'tools', 'thinking'] },\n { idPattern: /^grok-3/, capabilities: ['chat', 'tools'] },\n { idPattern: /^grok-2/, capabilities: ['chat', 'vision'] }\n ],\n 'google-gemini': [\n { idPattern: /^imagen/, capabilities: ['image-generation'] },\n { idPattern: /^gemini-.*-image/, capabilities: ['image-generation'] },\n { idPattern: /embedding/, capabilities: ['embedding'] },\n { idPattern: /^gemini-3/, capabilities: ['chat', 'tools', 'vision', 'thinking'] },\n { idPattern: /^gemini-2\\.5/, capabilities: ['chat', 'tools', 'vision', 'thinking'] },\n { idPattern: /^gemini-/, capabilities: ['chat', 'tools', 'vision'] }\n ],\n anthropic: [\n // Broadened from /^claude-opus-4/ and /^claude-sonnet-4/ so the sonnet-5+ / opus-5+ lines\n // are detected as thinking-capable. Detection accumulates across matching rules, so this is\n // purely additive: every existing opus-4 / sonnet-4 id still matches. Both broadenings are\n // now load-bearing: claude-sonnet-5 and claude-opus-5 (the advanced-tier target) would\n // otherwise hit only /^claude-/ and lose thinking. The fable rule keeps the\n // AnthropicThinkingModelNames union honest — claude-fable-5 (modelOverride-only) would\n // otherwise fall to the /^claude-/ catch-all and be detected without thinking.\n { idPattern: /^claude-opus-/, capabilities: ['chat', 'tools', 'vision', 'thinking'] },\n { idPattern: /^claude-sonnet-/, capabilities: ['chat', 'tools', 'vision', 'thinking'] },\n { idPattern: /^claude-fable-/, capabilities: ['chat', 'tools', 'vision', 'thinking'] },\n { idPattern: /^claude-/, capabilities: ['chat', 'tools', 'vision'] }\n ],\n groq: [{ idPattern: /./, capabilities: ['chat'] }],\n mistral: [\n { idPattern: /embed/, capabilities: ['embedding'] },\n { idPattern: /./, capabilities: ['chat'] }\n ],\n // Self-hosted OpenAI-compatible servers (Ollama, LM Studio, llama.cpp) serve\n // arbitrary, caller-chosen models whose ids we can't enumerate ahead of time.\n // The catch-all `/./` intentionally departs from the \"narrow patterns\" rule\n // above: assume `chat` for everything and let the caller override via\n // `capabilityConfig` when they know their deployment serves image/embedding models.\n ollama: [{ idPattern: /./, capabilities: ['chat'] }],\n 'openai-compat': [{ idPattern: /./, capabilities: ['chat'] }]\n }\n};\n"]}
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/registry.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n/**\n * Centralized provider registry — single source of truth for all AI provider metadata.\n * @packageDocumentation\n */\n\nimport { fail, Result, succeed } from '@fgv/ts-utils';\n\nimport {\n type AiProviderId,\n type IAiEmbeddingModelCapability,\n type IAiImageModelCapability,\n type IAiModelCapabilityConfig,\n type IAiProviderDescriptor,\n resolveModelAlias\n} from './model';\n\n// ============================================================================\n// Built-in providers\n// ============================================================================\n\n/**\n * All known AI provider descriptors. Copy-paste first, then alphabetical.\n * @internal\n */\nconst BUILTIN_PROVIDERS: ReadonlyArray<IAiProviderDescriptor> = [\n {\n id: 'copy-paste',\n label: 'Copy / Paste',\n buttonLabel: 'AI Assist | Copy',\n needsSecret: false,\n apiFormat: 'openai',\n baseUrl: '',\n defaultModel: '',\n supportedTools: [],\n corsRestricted: false,\n streamingCorsRestricted: false,\n acceptsImageInput: false,\n thinkingMode: 'unsupported'\n },\n {\n id: 'anthropic',\n label: 'Anthropic Claude',\n buttonLabel: 'AI Assist | Claude',\n needsSecret: true,\n apiFormat: 'anthropic',\n baseUrl: 'https://api.anthropic.com/v1',\n defaultModel: {\n base: '@anthropic:sonnet', // claude-sonnet-5 (was 'claude-sonnet-4-5-20250929')\n advanced: '@anthropic:opus' // claude-opus-5\n // no frontier key → a frontier request cascades advanced → opus (see resolveModel)\n },\n aliases: {\n '@anthropic:sonnet': 'claude-sonnet-5', // base tier\n '@anthropic:opus': 'claude-opus-5', // advanced tier (was claude-opus-4-8; opus-5 is the drop-in successor at the same price)\n '@anthropic:haiku': 'claude-haiku-4-5-20251001', // NON-tier alias; modelOverride only\n '@anthropic:fable': 'claude-fable-5' // NON-tier alias; modelOverride only\n // NOTE: no thinking/image/embedding keys — Anthropic completions are all text; base\n // (sonnet-5) and advanced (opus-5) are both thinking-capable, so a thinking-context\n // call flat-falls to base safely.\n },\n supportedTools: ['web_search'],\n corsRestricted: false,\n streamingCorsRestricted: false,\n acceptsImageInput: true,\n thinkingMode: 'optional',\n // Claude 5 family requires the adaptive thinking wire shape (thinking.type: 'adaptive' +\n // output_config.effort) and 400s on the legacy thinking.type: 'enabled' + budget_tokens\n // shape; see AiAssist.isAdaptiveThinkingModel.\n adaptiveThinkingModelPrefixes: ['claude-sonnet-5', 'claude-opus-5', 'claude-fable-5']\n },\n {\n id: 'google-gemini',\n label: 'Google Gemini',\n buttonLabel: 'AI Assist | Gemini',\n needsSecret: true,\n apiFormat: 'gemini',\n baseUrl: 'https://generativelanguage.googleapis.com/v1beta',\n defaultModel: {\n base: '@google-gemini:flash',\n advanced: '@google-gemini:pro', // reuses the existing @google-gemini:pro alias (no new alias entry)\n image: '@google-gemini:flash-image',\n embedding: '@google-gemini:embedding'\n // no frontier key → a frontier request cascades advanced → pro (see resolveModel)\n },\n aliases: {\n // NOTE: the base flash line is at 3.5 while pro / flash-lite / flash-image are at 3.1 — this is\n // NOT a typo. The targets come verbatim from Google's official deprecation table: the flash base\n // line advanced to 3.5 while the other roles are on the 3.1 generation. The per-role version\n // split is exactly why the alias layer exists — consumers never see these numbers.\n '@google-gemini:flash': 'gemini-3.5-flash', // base (was gemini-2.5-flash, shutdown 2026-10-16)\n '@google-gemini:pro': 'gemini-3.1-pro-preview', // advanced-tier role (wired to the 'advanced' defaultModel key); also the frontier cascade target (was gemini-2.5-pro, 2026-10-16)\n '@google-gemini:flash-lite': 'gemini-3.1-flash-lite', // cheaper thinking-capable line; available via modelOverride only (was gemini-2.5-flash-lite, 2026-10-16)\n '@google-gemini:flash-image': 'gemini-3.1-flash-image', // image (GA id; was gemini-3.1-flash-image-preview, retired 2026-06-25)\n '@google-gemini:embedding': 'gemini-embedding-001' // NOT deprecated — aliased for uniformity only\n },\n supportedTools: ['web_search'],\n corsRestricted: false,\n streamingCorsRestricted: false,\n acceptsImageInput: true,\n thinkingMode: 'optional',\n embedding: [\n {\n modelPrefix: '',\n format: 'gemini-embeddings',\n supportsDimensions: true,\n supportsTaskType: true,\n defaultDimensions: 3072\n }\n ],\n imageGeneration: [\n {\n // Gemini Flash Image: chat-style generateContent\n modelPrefix: '',\n format: 'gemini-image-out',\n acceptsImageReferenceInput: true,\n supportsQualityParam: false,\n maxCount: 1,\n outputParamStyle: 'none',\n defaultOutputMimeType: 'image/jpeg'\n }\n ]\n },\n {\n id: 'groq',\n label: 'Groq',\n buttonLabel: 'AI Assist | Groq',\n needsSecret: true,\n apiFormat: 'openai',\n baseUrl: 'https://api.groq.com/openai/v1',\n defaultModel: 'llama-3.3-70b-versatile',\n supportedTools: [],\n corsRestricted: false,\n streamingCorsRestricted: false,\n acceptsImageInput: false,\n thinkingMode: 'unsupported'\n },\n {\n id: 'mistral',\n label: 'Mistral',\n buttonLabel: 'AI Assist | Mistral',\n needsSecret: true,\n apiFormat: 'openai',\n baseUrl: 'https://api.mistral.ai/v1',\n defaultModel: { base: 'mistral-large-latest', embedding: 'mistral-embed' },\n supportedTools: [],\n corsRestricted: false,\n streamingCorsRestricted: false,\n acceptsImageInput: false,\n thinkingMode: 'unsupported',\n embedding: [{ modelPrefix: '', format: 'openai-embeddings' }]\n },\n {\n id: 'ollama',\n label: 'Ollama (self-hosted)',\n buttonLabel: 'AI Assist | Ollama',\n needsSecret: false,\n apiFormat: 'openai',\n baseUrl: 'http://localhost:11434/v1',\n defaultModel: '',\n supportedTools: [],\n corsRestricted: false,\n streamingCorsRestricted: false,\n acceptsImageInput: false,\n thinkingMode: 'unsupported',\n embedding: [{ modelPrefix: '', format: 'openai-embeddings' }]\n },\n {\n id: 'openai',\n label: 'OpenAI',\n buttonLabel: 'AI Assist | OpenAI',\n needsSecret: true,\n apiFormat: 'openai',\n baseUrl: 'https://api.openai.com/v1',\n defaultModel: {\n base: '@openai:mini', // gpt-5.6-luna (was gpt-5.4-mini; before that 'gpt-4o' — EOL-behind)\n advanced: '@openai:flagship', // gpt-5.6-terra\n // The gpt-5.6 family works on BOTH Chat Completions and the Responses API, so the\n // frontier tier no longer needs Responses-only routing. gpt-5.5-pro (the previous\n // frontier target) remains Responses-API-only and reachable via modelOverride; the\n // `responsesOnlyModelPrefixes` marker below still routes it correctly.\n frontier: '@openai:pro', // gpt-5.6-sol\n image: '@openai:image', // gpt-image-2 (was gpt-image-1.5; before that 'dall-e-3' — EOL 2026-05-12)\n embedding: '@openai:embedding' // text-embedding-3-small (unchanged, aliased for uniformity)\n },\n aliases: {\n '@openai:mini': 'gpt-5.6-luna', // base tier (was gpt-5.4-mini)\n '@openai:flagship': 'gpt-5.6-terra', // advanced tier (was gpt-5.5)\n '@openai:pro': 'gpt-5.6-sol', // frontier tier (was gpt-5.5-pro, which was Responses-API-only; 5.6 works on chat completions)\n '@openai:nano': 'gpt-5.4-nano', // NON-tier alias; modelOverride only\n '@openai:image': 'gpt-image-2', // image (matches the gpt-image- capability prefix; was gpt-image-1.5)\n '@openai:embedding': 'text-embedding-3-small' // NOT deprecated — aliased for uniformity\n // NOTE: gpt-5.1 deliberately absent — retired March 2026.\n },\n supportedTools: ['web_search'],\n corsRestricted: false,\n streamingCorsRestricted: false,\n acceptsImageInput: true,\n thinkingMode: 'optional',\n responsesOnlyModelPrefixes: ['gpt-5.5-pro'],\n embedding: [\n {\n modelPrefix: 'text-embedding-3',\n format: 'openai-embeddings',\n supportsDimensions: true,\n maxBatchSize: 2048\n },\n {\n modelPrefix: '',\n format: 'openai-embeddings'\n }\n ],\n imageGeneration: [\n {\n modelPrefix: 'gpt-image-',\n format: 'openai-images',\n acceptsImageReferenceInput: true,\n acceptedSizes: ['1024x1024', '1536x1024', '1024x1536', 'auto'],\n supportsQualityParam: true,\n acceptedQualities: ['low', 'medium', 'high', 'auto'],\n maxCount: 10,\n outputParamStyle: 'output-format',\n defaultOutputMimeType: 'image/png'\n },\n {\n modelPrefix: '',\n format: 'openai-images',\n outputParamStyle: 'response-format',\n defaultOutputMimeType: 'image/png'\n }\n ]\n },\n {\n id: 'openai-compat',\n label: 'OpenAI-compatible (self-hosted)',\n buttonLabel: 'AI Assist | OpenAI-compat',\n needsSecret: false,\n apiFormat: 'openai',\n baseUrl: '',\n defaultModel: '',\n supportedTools: [],\n corsRestricted: false,\n streamingCorsRestricted: false,\n acceptsImageInput: false,\n thinkingMode: 'unsupported',\n embedding: [{ modelPrefix: '', format: 'openai-embeddings' }]\n },\n {\n id: 'xai-grok',\n label: 'xAI Grok',\n buttonLabel: 'AI Assist | Grok',\n needsSecret: true,\n apiFormat: 'openai',\n baseUrl: 'https://api.x.ai/v1',\n defaultModel: {\n base: '@xai-grok:standard', // grok-4.3 (was the raw id; the cheap line + retirement-wave redirect target)\n advanced: '@xai-grok:flagship', // grok-4.5 (flagship since 2026-07-08; $2/$6 sits in the advanced band)\n image: '@xai-grok:imagine' // grok-imagine-image-quality (was the raw id)\n // no frontier key → a frontier request cascades advanced → grok-4.5 (see resolveModel)\n },\n aliases: {\n '@xai-grok:standard': 'grok-4.3', // base tier; NOT deprecated — superseded as flagship by grok-4.5\n '@xai-grok:flagship': 'grok-4.5', // advanced tier; configurable reasoning effort (default high)\n '@xai-grok:imagine': 'grok-imagine-image-quality' // image tier; current (redirect target for the retired -pro)\n },\n supportedTools: ['web_search'],\n corsRestricted: true,\n streamingCorsRestricted: true,\n acceptsImageInput: true,\n thinkingMode: 'optional',\n imageGeneration: [\n {\n // grok-imagine models use JSON edits with image_url objects (different wire format)\n modelPrefix: 'grok-imagine-',\n format: 'xai-images-edits',\n acceptsImageReferenceInput: true,\n supportsQualityParam: false,\n maxCount: 10,\n outputParamStyle: 'response-format',\n defaultOutputMimeType: 'image/jpeg'\n },\n {\n // catch-all for other xai image models\n modelPrefix: '',\n format: 'xai-images',\n acceptsImageReferenceInput: false,\n supportsQualityParam: false,\n maxCount: 10,\n outputParamStyle: 'response-format',\n defaultOutputMimeType: 'image/jpeg'\n }\n ]\n }\n];\n\n/**\n * Index for O(1) lookup by id.\n * @internal\n */\nconst PROVIDER_BY_ID: ReadonlyMap<string, IAiProviderDescriptor> = new Map(\n BUILTIN_PROVIDERS.map((d) => [d.id, d])\n);\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * All valid provider ID values, in the same order as the registry.\n * @public\n */\nexport const allProviderIds: ReadonlyArray<AiProviderId> = BUILTIN_PROVIDERS.map((d) => d.id);\n\n/**\n * Get all known provider descriptors. Copy-paste first, then alphabetical.\n * @returns All built-in provider descriptors\n * @public\n */\nexport function getProviderDescriptors(): ReadonlyArray<IAiProviderDescriptor> {\n return BUILTIN_PROVIDERS;\n}\n\n/**\n * Get a provider descriptor by id.\n * @param id - The provider identifier\n * @returns The descriptor, or a failure if the provider is unknown\n * @public\n */\nexport function getProviderDescriptor(id: string): Result<IAiProviderDescriptor> {\n const descriptor = PROVIDER_BY_ID.get(id);\n if (!descriptor) {\n return fail(`unknown AI provider: ${id}`);\n }\n return succeed(descriptor);\n}\n\n/**\n * Whether a provider declares any image-generation capability at all.\n *\n * @param descriptor - The provider descriptor\n * @returns `true` when {@link IAiProviderDescriptor.imageGeneration} has at\n * least one entry; `false` otherwise.\n * @public\n */\nexport function supportsImageGeneration(descriptor: IAiProviderDescriptor): boolean {\n return (descriptor.imageGeneration?.length ?? 0) > 0;\n}\n\n/**\n * Shared longest-prefix capability match, alias-guarded.\n *\n * @remarks\n * `modelId` is resolved through `resolveModelAlias` **before** any prefix\n * matching, so an fgv alias (`@<provider>:<role>`) and the concrete id it names\n * select the same capability. Without this step an alias would fall through to\n * the `modelPrefix: ''` catch-all every provider declares and yield a\n * confidently wrong capability rather than no capability.\n *\n * An unresolvable alias (sigil-prefixed but unregistered, or cyclic) names no\n * model, so no capability applies and the match is skipped entirely — it must\n * never be prefix-matched verbatim. Callers already treat `undefined` as \"this\n * provider has no capability for this model\" and fail with that message.\n *\n * A concrete (non-sigil) id passes through `resolveModelAlias` verbatim, so\n * behavior for every raw provider id is unchanged.\n * @internal\n */\nfunction resolveCapabilityForModel<TCapability extends { readonly modelPrefix: string }>(\n descriptor: IAiProviderDescriptor,\n modelId: string,\n capabilities: ReadonlyArray<TCapability> | undefined\n): TCapability | undefined {\n const concreteModelId = resolveModelAlias(descriptor, modelId).orDefault();\n if (concreteModelId === undefined) {\n return undefined;\n }\n return (capabilities ?? [])\n .filter((cap) => concreteModelId.startsWith(cap.modelPrefix))\n .reduce<TCapability | undefined>(\n (best, cap) => (best && best.modelPrefix.length >= cap.modelPrefix.length ? best : cap),\n undefined\n );\n}\n\n/**\n * Resolve the image-generation capability that applies to a given model id\n * for a provider. Returns the entry from\n * {@link IAiProviderDescriptor.imageGeneration} whose `modelPrefix` is the\n * longest prefix of `modelId`. Ties are broken by first-encountered, so rule\n * order does not matter for correctness — only for tie-breaking among rules\n * with identical-length prefixes (an unusual case).\n *\n * @remarks\n * `modelId` may be either a concrete provider model id or an fgv model alias\n * (`@<provider>:<role>`, see `MODEL_ALIAS_SIGIL`) — it is resolved via\n * `resolveModelAlias` against `descriptor.aliases` before prefix matching,\n * so both forms select the same capability. A raw provider id passes through\n * unchanged. An alias that is not registered on `descriptor` (or is cyclic)\n * names no model and yields `undefined` rather than falling through to the\n * `modelPrefix: ''` catch-all.\n *\n * @param descriptor - The provider descriptor\n * @param modelId - The image model id — concrete or an fgv alias\n * @returns The matching capability, or `undefined` when no rule matches, the\n * provider declares no image-generation capabilities, or `modelId` is an\n * unresolvable alias.\n * @public\n */\nexport function resolveImageCapability(\n descriptor: IAiProviderDescriptor,\n modelId: string\n): IAiImageModelCapability | undefined {\n return resolveCapabilityForModel(descriptor, modelId, descriptor.imageGeneration);\n}\n\n/**\n * Whether a provider declares any embedding capability at all.\n *\n * @param descriptor - The provider descriptor\n * @returns `true` when {@link IAiProviderDescriptor.embedding} has at least one\n * entry; `false` otherwise.\n * @public\n */\nexport function supportsEmbedding(descriptor: IAiProviderDescriptor): boolean {\n return (descriptor.embedding?.length ?? 0) > 0;\n}\n\n/**\n * Resolve the embedding capability that applies to a given model id for a\n * provider. Returns the entry from {@link IAiProviderDescriptor.embedding} whose\n * `modelPrefix` is the longest prefix of `modelId`. Ties are broken by\n * first-encountered.\n *\n * @remarks\n * `modelId` may be either a concrete provider model id or an fgv model alias\n * (`@<provider>:<role>`, see `MODEL_ALIAS_SIGIL`) — it is resolved via\n * `resolveModelAlias` against `descriptor.aliases` before prefix matching,\n * so both forms select the same capability. A raw provider id passes through\n * unchanged. An alias that is not registered on `descriptor` (or is cyclic)\n * names no model and yields `undefined` rather than falling through to the\n * `modelPrefix: ''` catch-all.\n *\n * @param descriptor - The provider descriptor\n * @param modelId - The embedding model id — concrete or an fgv alias\n * @returns The matching capability, or `undefined` when no rule matches, the\n * provider declares no embedding capabilities, or `modelId` is an\n * unresolvable alias.\n * @public\n */\nexport function resolveEmbeddingCapability(\n descriptor: IAiProviderDescriptor,\n modelId: string\n): IAiEmbeddingModelCapability | undefined {\n return resolveCapabilityForModel(descriptor, modelId, descriptor.embedding);\n}\n\n// ============================================================================\n// Default model capability config\n// ============================================================================\n\n/**\n * Default capability config used by `callProviderListModels` when callers\n * don't supply their own. Patterns are intentionally narrow — false\n * positives are worse than missing a model. Caller can override per call\n * via {@link IProviderListModelsParams.capabilityConfig}.\n *\n * @public\n */\nexport const DEFAULT_MODEL_CAPABILITY_CONFIG: IAiModelCapabilityConfig = {\n perProvider: {\n openai: [\n { idPattern: /^gpt-image/, capabilities: ['image-generation'] },\n { idPattern: /^text-embedding/, capabilities: ['embedding'] },\n { idPattern: /^gpt-5/, capabilities: ['chat', 'tools', 'vision', 'thinking'] },\n { idPattern: /^gpt-4/, capabilities: ['chat', 'tools', 'vision'] },\n { idPattern: /^gpt-3\\.5/, capabilities: ['chat'] },\n { idPattern: /^o\\d/, capabilities: ['chat', 'tools', 'thinking'] }\n ],\n 'xai-grok': [\n { idPattern: /-image/, capabilities: ['image-generation'] },\n // grok-4.5 needs its own rule: it would otherwise hit only /^grok-4/ and lose\n // thinking, yet it has configurable reasoning effort. Detection accumulates across\n // matching rules, so /^grok-4/ still contributes vision (same as grok-4.3).\n { idPattern: /^grok-4\\.5/, capabilities: ['chat', 'tools', 'thinking'] },\n { idPattern: /^grok-4\\.3/, capabilities: ['chat', 'tools', 'thinking'] },\n { idPattern: /^grok-4$/, capabilities: ['chat', 'tools', 'thinking'] },\n { idPattern: /^grok-4/, capabilities: ['chat', 'tools', 'vision'] },\n { idPattern: /^grok-3-mini/, capabilities: ['chat', 'tools', 'thinking'] },\n { idPattern: /^grok-3/, capabilities: ['chat', 'tools'] },\n { idPattern: /^grok-2/, capabilities: ['chat', 'vision'] }\n ],\n 'google-gemini': [\n { idPattern: /^imagen/, capabilities: ['image-generation'] },\n { idPattern: /^gemini-.*-image/, capabilities: ['image-generation'] },\n { idPattern: /embedding/, capabilities: ['embedding'] },\n { idPattern: /^gemini-3/, capabilities: ['chat', 'tools', 'vision', 'thinking'] },\n { idPattern: /^gemini-2\\.5/, capabilities: ['chat', 'tools', 'vision', 'thinking'] },\n { idPattern: /^gemini-/, capabilities: ['chat', 'tools', 'vision'] }\n ],\n anthropic: [\n // Broadened from /^claude-opus-4/ and /^claude-sonnet-4/ so the sonnet-5+ / opus-5+ lines\n // are detected as thinking-capable. Detection accumulates across matching rules, so this is\n // purely additive: every existing opus-4 / sonnet-4 id still matches. Both broadenings are\n // now load-bearing: claude-sonnet-5 and claude-opus-5 (the advanced-tier target) would\n // otherwise hit only /^claude-/ and lose thinking. The fable rule keeps the\n // AnthropicThinkingModelNames union honest — claude-fable-5 (modelOverride-only) would\n // otherwise fall to the /^claude-/ catch-all and be detected without thinking.\n { idPattern: /^claude-opus-/, capabilities: ['chat', 'tools', 'vision', 'thinking'] },\n { idPattern: /^claude-sonnet-/, capabilities: ['chat', 'tools', 'vision', 'thinking'] },\n { idPattern: /^claude-fable-/, capabilities: ['chat', 'tools', 'vision', 'thinking'] },\n { idPattern: /^claude-/, capabilities: ['chat', 'tools', 'vision'] }\n ],\n groq: [{ idPattern: /./, capabilities: ['chat'] }],\n mistral: [\n { idPattern: /embed/, capabilities: ['embedding'] },\n { idPattern: /./, capabilities: ['chat'] }\n ],\n // Self-hosted OpenAI-compatible servers (Ollama, LM Studio, llama.cpp) serve\n // arbitrary, caller-chosen models whose ids we can't enumerate ahead of time.\n // The catch-all `/./` intentionally departs from the \"narrow patterns\" rule\n // above: assume `chat` for everything and let the caller override via\n // `capabilityConfig` when they know their deployment serves image/embedding models.\n ollama: [{ idPattern: /./, capabilities: ['chat'] }],\n 'openai-compat': [{ idPattern: /./, capabilities: ['chat'] }]\n }\n};\n"]}
|
|
@@ -4,9 +4,15 @@ import { FileTree, JsonValue } from '@fgv/ts-json-base';
|
|
|
4
4
|
* Implementation of `FileTree.IFileTreeFileItem` for files in a ZIP archive.
|
|
5
5
|
* ZIP files are read-only, so this item does not support mutation.
|
|
6
6
|
* Use {@link FileTree.isMutableFileItem | isMutableFileItem} to check before attempting mutations.
|
|
7
|
+
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* ZIP entries are byte-native, so this item also implements the read half of the
|
|
10
|
+
* optional binary capability (`FileTree.IBinaryFileTreeFileItem`) — use
|
|
11
|
+
* `FileTree.isBinaryFileItem` to narrow and `getRawBytes()` to read the entry's
|
|
12
|
+
* undecoded bytes.
|
|
7
13
|
* @public
|
|
8
14
|
*/
|
|
9
|
-
export declare class ZipFileItem<TCT extends string = string> implements FileTree.
|
|
15
|
+
export declare class ZipFileItem<TCT extends string = string> implements FileTree.IBinaryFileTreeFileItem<TCT> {
|
|
10
16
|
/**
|
|
11
17
|
* Indicates that this `FileTree.FileTreeItem` is a file.
|
|
12
18
|
*/
|
|
@@ -32,9 +38,13 @@ export declare class ZipFileItem<TCT extends string = string> implements FileTre
|
|
|
32
38
|
*/
|
|
33
39
|
get contentType(): TCT | undefined;
|
|
34
40
|
/**
|
|
35
|
-
* The pre-loaded
|
|
41
|
+
* The pre-loaded raw bytes of the ZIP entry.
|
|
36
42
|
*/
|
|
37
|
-
private readonly
|
|
43
|
+
private readonly _bytes;
|
|
44
|
+
/**
|
|
45
|
+
* Text form of the entry, decoded lazily from the raw bytes on first text read.
|
|
46
|
+
*/
|
|
47
|
+
private _contents;
|
|
38
48
|
/**
|
|
39
49
|
* The ZIP file tree accessors that created this item.
|
|
40
50
|
*/
|
|
@@ -50,10 +60,12 @@ export declare class ZipFileItem<TCT extends string = string> implements FileTre
|
|
|
50
60
|
/**
|
|
51
61
|
* Constructor for ZipFileItem.
|
|
52
62
|
* @param zipFilePath - The path of the file within the ZIP.
|
|
53
|
-
* @param contents - The pre-loaded contents of the
|
|
63
|
+
* @param contents - The pre-loaded contents of the entry, either as raw bytes or as
|
|
64
|
+
* already-decoded text. Text is encoded as UTF-8 for the byte accessor and is also
|
|
65
|
+
* retained verbatim, so supplying text never round-trips through a decode.
|
|
54
66
|
* @param accessors - The ZIP file tree accessors.
|
|
55
67
|
*/
|
|
56
|
-
constructor(zipFilePath: string, contents: string, accessors: ZipFileTreeAccessors<TCT>);
|
|
68
|
+
constructor(zipFilePath: string, contents: string | Uint8Array, accessors: ZipFileTreeAccessors<TCT>);
|
|
57
69
|
/**
|
|
58
70
|
* Sets the content type of the file.
|
|
59
71
|
* @param contentType - The content type of the file.
|
|
@@ -66,8 +78,21 @@ export declare class ZipFileItem<TCT extends string = string> implements FileTre
|
|
|
66
78
|
getContents<T>(converter: Validator<T> | Converter<T>): Result<T>;
|
|
67
79
|
/**
|
|
68
80
|
* Gets the raw contents of the file as a string.
|
|
81
|
+
*
|
|
82
|
+
* @remarks
|
|
83
|
+
* The entry's bytes are decoded as UTF-8 with the lenient WHATWG default, so
|
|
84
|
+
* malformed input is silently replaced with U+FFFD. Use `getRawBytes()` for the
|
|
85
|
+
* undecoded bytes — and `new TextDecoder('utf-8', { fatal: true }).decode(bytes)`
|
|
86
|
+
* for a decode that fails loudly instead.
|
|
69
87
|
*/
|
|
70
88
|
getRawContents(): Result<string>;
|
|
89
|
+
/**
|
|
90
|
+
* Gets the raw bytes of the ZIP entry, with no text decoding applied.
|
|
91
|
+
*
|
|
92
|
+
* @remarks
|
|
93
|
+
* The returned array is the item's internal buffer and must not be modified.
|
|
94
|
+
*/
|
|
95
|
+
getRawBytes(): Result<Uint8Array>;
|
|
71
96
|
}
|
|
72
97
|
/**
|
|
73
98
|
* Implementation of `IFileTreeDirectoryItem` for directories in a ZIP archive.
|
|
@@ -105,9 +130,15 @@ export declare class ZipDirectoryItem<TCT extends string = string> implements Fi
|
|
|
105
130
|
* Read-only file tree accessors for ZIP archives.
|
|
106
131
|
* ZIP archives are read-only by design — use {@link FileTree.isMutableAccessors | isMutableAccessors}
|
|
107
132
|
* to check before attempting mutations.
|
|
133
|
+
*
|
|
134
|
+
* @remarks
|
|
135
|
+
* ZIP entries are byte-native, so these accessors also implement the read half of the
|
|
136
|
+
* optional binary capability (`FileTree.IBinaryFileTreeAccessors`) — use
|
|
137
|
+
* `FileTree.isBinaryAccessors` to narrow and `getFileBytes()` to read an entry's
|
|
138
|
+
* undecoded bytes.
|
|
108
139
|
* @public
|
|
109
140
|
*/
|
|
110
|
-
export declare class ZipFileTreeAccessors<TCT extends string = string> implements FileTree.
|
|
141
|
+
export declare class ZipFileTreeAccessors<TCT extends string = string> implements FileTree.IBinaryFileTreeAccessors<TCT> {
|
|
111
142
|
/**
|
|
112
143
|
* The unzipped file data.
|
|
113
144
|
*/
|
|
@@ -201,8 +232,25 @@ export declare class ZipFileTreeAccessors<TCT extends string = string> implement
|
|
|
201
232
|
getItem(path: string): Result<FileTree.FileTreeItem<TCT>>;
|
|
202
233
|
/**
|
|
203
234
|
* Gets the contents of a file in the file tree.
|
|
235
|
+
*
|
|
236
|
+
* @remarks
|
|
237
|
+
* The entry's bytes are decoded as UTF-8 with the lenient WHATWG default. Use
|
|
238
|
+
* `getFileBytes()` for the undecoded bytes.
|
|
204
239
|
*/
|
|
205
240
|
getFileContents(path: string): Result<string>;
|
|
241
|
+
/**
|
|
242
|
+
* Gets the raw bytes of a ZIP entry, with no text decoding applied.
|
|
243
|
+
*
|
|
244
|
+
* @remarks
|
|
245
|
+
* The returned array is the archive's internal buffer and must not be modified.
|
|
246
|
+
*/
|
|
247
|
+
getFileBytes(path: string): Result<Uint8Array>;
|
|
248
|
+
/**
|
|
249
|
+
* Resolves a path to the ZIP file item it names.
|
|
250
|
+
* @param path - Path of the entry to look up.
|
|
251
|
+
* @returns `Success` with the item, or `Failure` if it is missing or is a directory.
|
|
252
|
+
*/
|
|
253
|
+
private _getFileItem;
|
|
206
254
|
/**
|
|
207
255
|
* Gets the content type of a file in the file tree.
|
|
208
256
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zipFileTreeAccessors.d.ts","sourceRoot":"","sources":["../../../src/packlets/zip-file-tree/zipFileTreeAccessors.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,MAAM,EAAgC,SAAS,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAExD
|
|
1
|
+
{"version":3,"file":"zipFileTreeAccessors.d.ts","sourceRoot":"","sources":["../../../src/packlets/zip-file-tree/zipFileTreeAccessors.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,6 +28,12 @@ const ts_utils_1 = require("@fgv/ts-utils");
|
|
|
28
28
|
* Implementation of `FileTree.IFileTreeFileItem` for files in a ZIP archive.
|
|
29
29
|
* ZIP files are read-only, so this item does not support mutation.
|
|
30
30
|
* Use {@link FileTree.isMutableFileItem | isMutableFileItem} to check before attempting mutations.
|
|
31
|
+
*
|
|
32
|
+
* @remarks
|
|
33
|
+
* ZIP entries are byte-native, so this item also implements the read half of the
|
|
34
|
+
* optional binary capability (`FileTree.IBinaryFileTreeFileItem`) — use
|
|
35
|
+
* `FileTree.isBinaryFileItem` to narrow and `getRawBytes()` to read the entry's
|
|
36
|
+
* undecoded bytes.
|
|
31
37
|
* @public
|
|
32
38
|
*/
|
|
33
39
|
class ZipFileItem {
|
|
@@ -44,7 +50,9 @@ class ZipFileItem {
|
|
|
44
50
|
/**
|
|
45
51
|
* Constructor for ZipFileItem.
|
|
46
52
|
* @param zipFilePath - The path of the file within the ZIP.
|
|
47
|
-
* @param contents - The pre-loaded contents of the
|
|
53
|
+
* @param contents - The pre-loaded contents of the entry, either as raw bytes or as
|
|
54
|
+
* already-decoded text. Text is encoded as UTF-8 for the byte accessor and is also
|
|
55
|
+
* retained verbatim, so supplying text never round-trips through a decode.
|
|
48
56
|
* @param accessors - The ZIP file tree accessors.
|
|
49
57
|
*/
|
|
50
58
|
constructor(zipFilePath, contents, accessors) {
|
|
@@ -56,7 +64,13 @@ class ZipFileItem {
|
|
|
56
64
|
* Flag to track if content type should be inferred on first access.
|
|
57
65
|
*/
|
|
58
66
|
this._shouldInferContentType = true;
|
|
59
|
-
|
|
67
|
+
if (typeof contents === 'string') {
|
|
68
|
+
this._contents = contents;
|
|
69
|
+
this._bytes = new TextEncoder().encode(contents);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
this._bytes = contents;
|
|
73
|
+
}
|
|
60
74
|
this._accessors = accessors;
|
|
61
75
|
this.absolutePath = '/' + zipFilePath;
|
|
62
76
|
this.name = accessors.getBaseName(zipFilePath);
|
|
@@ -91,10 +105,28 @@ class ZipFileItem {
|
|
|
91
105
|
}
|
|
92
106
|
/**
|
|
93
107
|
* Gets the raw contents of the file as a string.
|
|
108
|
+
*
|
|
109
|
+
* @remarks
|
|
110
|
+
* The entry's bytes are decoded as UTF-8 with the lenient WHATWG default, so
|
|
111
|
+
* malformed input is silently replaced with U+FFFD. Use `getRawBytes()` for the
|
|
112
|
+
* undecoded bytes — and `new TextDecoder('utf-8', { fatal: true }).decode(bytes)`
|
|
113
|
+
* for a decode that fails loudly instead.
|
|
94
114
|
*/
|
|
95
115
|
getRawContents() {
|
|
116
|
+
if (this._contents === undefined) {
|
|
117
|
+
this._contents = new TextDecoder().decode(this._bytes);
|
|
118
|
+
}
|
|
96
119
|
return (0, ts_utils_1.succeed)(this._contents);
|
|
97
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Gets the raw bytes of the ZIP entry, with no text decoding applied.
|
|
123
|
+
*
|
|
124
|
+
* @remarks
|
|
125
|
+
* The returned array is the item's internal buffer and must not be modified.
|
|
126
|
+
*/
|
|
127
|
+
getRawBytes() {
|
|
128
|
+
return (0, ts_utils_1.succeed)(this._bytes);
|
|
129
|
+
}
|
|
98
130
|
}
|
|
99
131
|
exports.ZipFileItem = ZipFileItem;
|
|
100
132
|
/**
|
|
@@ -128,6 +160,12 @@ exports.ZipDirectoryItem = ZipDirectoryItem;
|
|
|
128
160
|
* Read-only file tree accessors for ZIP archives.
|
|
129
161
|
* ZIP archives are read-only by design — use {@link FileTree.isMutableAccessors | isMutableAccessors}
|
|
130
162
|
* to check before attempting mutations.
|
|
163
|
+
*
|
|
164
|
+
* @remarks
|
|
165
|
+
* ZIP entries are byte-native, so these accessors also implement the read half of the
|
|
166
|
+
* optional binary capability (`FileTree.IBinaryFileTreeAccessors`) — use
|
|
167
|
+
* `FileTree.isBinaryAccessors` to narrow and `getFileBytes()` to read an entry's
|
|
168
|
+
* undecoded bytes.
|
|
131
169
|
* @public
|
|
132
170
|
*/
|
|
133
171
|
class ZipFileTreeAccessors {
|
|
@@ -233,10 +271,9 @@ class ZipFileTreeAccessors {
|
|
|
233
271
|
directories.add(dirPath);
|
|
234
272
|
}
|
|
235
273
|
}
|
|
236
|
-
// Add the file item with its
|
|
274
|
+
// Add the file item with its raw bytes; text is decoded lazily on demand.
|
|
237
275
|
const absolutePath = this.resolveAbsolutePath(relativePath);
|
|
238
|
-
const
|
|
239
|
-
const item = new ZipFileItem(relativePath, contents, this);
|
|
276
|
+
const item = new ZipFileItem(relativePath, fileData, this);
|
|
240
277
|
this._itemCache.set(absolutePath, item);
|
|
241
278
|
}
|
|
242
279
|
}
|
|
@@ -298,13 +335,34 @@ class ZipFileTreeAccessors {
|
|
|
298
335
|
}
|
|
299
336
|
/**
|
|
300
337
|
* Gets the contents of a file in the file tree.
|
|
338
|
+
*
|
|
339
|
+
* @remarks
|
|
340
|
+
* The entry's bytes are decoded as UTF-8 with the lenient WHATWG default. Use
|
|
341
|
+
* `getFileBytes()` for the undecoded bytes.
|
|
301
342
|
*/
|
|
302
343
|
getFileContents(path) {
|
|
344
|
+
return this._getFileItem(path).onSuccess((item) => item.getRawContents());
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Gets the raw bytes of a ZIP entry, with no text decoding applied.
|
|
348
|
+
*
|
|
349
|
+
* @remarks
|
|
350
|
+
* The returned array is the archive's internal buffer and must not be modified.
|
|
351
|
+
*/
|
|
352
|
+
getFileBytes(path) {
|
|
353
|
+
return this._getFileItem(path).onSuccess((item) => item.getRawBytes());
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Resolves a path to the ZIP file item it names.
|
|
357
|
+
* @param path - Path of the entry to look up.
|
|
358
|
+
* @returns `Success` with the item, or `Failure` if it is missing or is a directory.
|
|
359
|
+
*/
|
|
360
|
+
_getFileItem(path) {
|
|
303
361
|
return this.getItem(path).onSuccess((item) => {
|
|
304
|
-
if (item
|
|
362
|
+
if (!(item instanceof ZipFileItem)) {
|
|
305
363
|
return (0, ts_utils_1.fail)(`Path is not a file: ${path}`);
|
|
306
364
|
}
|
|
307
|
-
return
|
|
365
|
+
return (0, ts_utils_1.succeed)(item);
|
|
308
366
|
});
|
|
309
367
|
}
|
|
310
368
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zipFileTreeAccessors.js","sourceRoot":"","sources":["../../../src/packlets/zip-file-tree/zipFileTreeAccessors.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2025 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { unzipSync, unzip, Unzipped } from 'fflate';\nimport { Result, succeed, fail, captureResult, Converter, Validator } from '@fgv/ts-utils';\nimport { FileTree, JsonValue } from '@fgv/ts-json-base';\n\n/**\n * Implementation of `FileTree.IFileTreeFileItem` for files in a ZIP archive.\n * ZIP files are read-only, so this item does not support mutation.\n * Use {@link FileTree.isMutableFileItem | isMutableFileItem} to check before attempting mutations.\n * @public\n */\nexport class ZipFileItem<TCT extends string = string> implements FileTree.IFileTreeFileItem<TCT> {\n /**\n * Indicates that this `FileTree.FileTreeItem` is a file.\n */\n public readonly type: 'file' = 'file';\n\n /**\n * The absolute path of the file within the ZIP archive.\n */\n public readonly absolutePath: string;\n\n /**\n * The name of the file\n */\n public readonly name: string;\n\n /**\n * The base name of the file (without extension)\n */\n public readonly baseName: string;\n\n /**\n * The extension of the file\n */\n public readonly extension: string;\n\n /**\n * The content type of the file.\n */\n public get contentType(): TCT | undefined {\n if (this._contentType === undefined && this._shouldInferContentType) {\n this._contentType = this._accessors.getFileContentType(this.absolutePath).orDefault();\n this._shouldInferContentType = false;\n }\n return this._contentType;\n }\n\n /**\n * The pre-loaded contents of the file.\n */\n private readonly _contents: string;\n\n /**\n * The ZIP file tree accessors that created this item.\n */\n private readonly _accessors: ZipFileTreeAccessors<TCT>;\n\n /**\n * Mutable content type of the file.\n */\n private _contentType: TCT | undefined;\n\n /**\n * Flag to track if content type should be inferred on first access.\n */\n private _shouldInferContentType: boolean = true;\n\n /**\n * Constructor for ZipFileItem.\n * @param zipFilePath - The path of the file within the ZIP.\n * @param contents - The pre-loaded contents of the file.\n * @param accessors - The ZIP file tree accessors.\n */\n public constructor(zipFilePath: string, contents: string, accessors: ZipFileTreeAccessors<TCT>) {\n this._contents = contents;\n this._accessors = accessors;\n this.absolutePath = '/' + zipFilePath;\n this.name = accessors.getBaseName(zipFilePath);\n this.extension = accessors.getExtension(zipFilePath);\n this.baseName = accessors.getBaseName(zipFilePath, this.extension);\n }\n\n /**\n * Sets the content type of the file.\n * @param contentType - The content type of the file.\n */\n public setContentType(contentType: TCT | undefined): void {\n this._contentType = contentType;\n this._shouldInferContentType = false;\n }\n\n /**\n * Gets the contents of the file as parsed JSON.\n */\n public getContents(): Result<JsonValue>;\n public getContents<T>(converter: Validator<T> | Converter<T>): Result<T>;\n public getContents<T>(converter?: Validator<T> | Converter<T>): Result<T | JsonValue> {\n return this.getRawContents()\n .onSuccess((contents) => {\n return captureResult(() => JSON.parse(contents))\n .onSuccess((parsed) => {\n if (converter) {\n return converter.convert(parsed) as Result<T | JsonValue>;\n }\n return succeed(parsed as JsonValue);\n })\n .onFailure(() => {\n return fail(`Failed to parse JSON from file: ${this.absolutePath}`);\n });\n })\n .onFailure((error) => {\n return fail(`Failed to get contents from file: ${error}`);\n });\n }\n\n /**\n * Gets the raw contents of the file as a string.\n */\n public getRawContents(): Result<string> {\n return succeed(this._contents);\n }\n}\n\n/**\n * Implementation of `IFileTreeDirectoryItem` for directories in a ZIP archive.\n * @public\n */\nexport class ZipDirectoryItem<TCT extends string = string> implements FileTree.IFileTreeDirectoryItem<TCT> {\n /**\n * Indicates that this `FileTree.FileTreeItem` is a directory.\n */\n public readonly type: 'directory' = 'directory';\n\n /**\n * The absolute path of the directory within the ZIP archive.\n */\n public readonly absolutePath: string;\n\n /**\n * The name of the directory\n */\n public readonly name: string;\n\n /**\n * The ZIP file tree accessors that created this item.\n */\n private readonly _accessors: ZipFileTreeAccessors<TCT>;\n\n /**\n * Constructor for ZipDirectoryItem.\n * @param directoryPath - The path of the directory within the ZIP.\n * @param accessors - The ZIP file tree accessors.\n */\n public constructor(directoryPath: string, accessors: ZipFileTreeAccessors<TCT>) {\n this._accessors = accessors;\n this.absolutePath = '/' + directoryPath.replace(/\\/$/, ''); // Normalize path\n this.name = accessors.getBaseName(directoryPath);\n }\n\n /**\n * Gets the children of the directory.\n */\n public getChildren(): Result<ReadonlyArray<FileTree.FileTreeItem<TCT>>> {\n return this._accessors.getChildren(this.absolutePath);\n }\n}\n\n/**\n * Read-only file tree accessors for ZIP archives.\n * ZIP archives are read-only by design — use {@link FileTree.isMutableAccessors | isMutableAccessors}\n * to check before attempting mutations.\n * @public\n */\nexport class ZipFileTreeAccessors<TCT extends string = string> implements FileTree.IFileTreeAccessors<TCT> {\n /**\n * The unzipped file data.\n */\n private readonly _files: Unzipped;\n\n /**\n * Optional prefix to prepend to paths.\n */\n private readonly _prefix: string;\n\n /**\n * Content type inference function.\n */\n private readonly _inferContentType: FileTree.ContentTypeFactory<TCT>;\n\n /**\n * Cache of all items in the ZIP for efficient lookups.\n */\n private readonly _itemCache: Map<string, FileTree.FileTreeItem<TCT>> = new Map();\n\n /**\n * Constructor for ZipFileTreeAccessors.\n * @param files - The unzipped file data from fflate.\n * @param params - Optional initialization parameters.\n */\n private constructor(files: Unzipped, params?: FileTree.IFileTreeInitParams<TCT>) {\n this._files = files;\n this._prefix = params?.prefix || '';\n this._inferContentType = params?.inferContentType ?? ZipFileTreeAccessors.defaultInferContentType;\n this._buildItemCache();\n }\n\n /**\n * Default function to infer the content type of a file.\n * @param __filePath - The path of the file.\n * @param __provided - Optional supplied content type.\n * @returns `Success` with the content type of the file if successful, or\n * `Failure` with an error message otherwise.\n * @remarks This default implementation always returns `Success` with `undefined`.\n * @public\n */\n public static defaultInferContentType<TCT extends string = string>(\n __filePath: string,\n __provided?: string\n ): Result<TCT | undefined> {\n return succeed(undefined);\n }\n\n /**\n * Creates a new ZipFileTreeAccessors instance from a ZIP file buffer (synchronous).\n * @param zipBuffer - The ZIP file as an ArrayBuffer or Uint8Array.\n * @param prefix - Optional prefix to prepend to paths.\n * @returns Result containing the ZipFileTreeAccessors instance.\n */\n public static fromBuffer<TCT extends string = string>(\n zipBuffer: ArrayBuffer | Uint8Array,\n prefix?: string\n ): Result<ZipFileTreeAccessors<TCT>>;\n\n /**\n * Creates a new ZipFileTreeAccessors instance from a ZIP file buffer (synchronous).\n * @param zipBuffer - The ZIP file as an ArrayBuffer or Uint8Array.\n * @param params - Optional initialization parameters.\n * @returns Result containing the ZipFileTreeAccessors instance.\n */\n public static fromBuffer<TCT extends string = string>(\n zipBuffer: ArrayBuffer | Uint8Array,\n params?: FileTree.IFileTreeInitParams<TCT>\n ): Result<ZipFileTreeAccessors<TCT>>;\n\n public static fromBuffer<TCT extends string = string>(\n zipBuffer: ArrayBuffer | Uint8Array,\n params?: FileTree.IFileTreeInitParams<TCT> | string\n ): Result<ZipFileTreeAccessors<TCT>> {\n try {\n /* c8 ignore next 1 - defense in depth */\n const uint8Buffer = zipBuffer instanceof Uint8Array ? zipBuffer : new Uint8Array(zipBuffer);\n const files = unzipSync(uint8Buffer);\n const normalizedParams = typeof params === 'string' ? { prefix: params } : params;\n return succeed(new ZipFileTreeAccessors<TCT>(files, normalizedParams));\n } catch (error) {\n /* c8 ignore next 1 - defensive coding: fflate always throws Error objects in practice */\n return fail(`Failed to load ZIP archive: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n /**\n * Creates a new ZipFileTreeAccessors instance from a ZIP file buffer (asynchronous).\n * @param zipBuffer - The ZIP file as an ArrayBuffer or Uint8Array.\n * @param prefix - Optional prefix to prepend to paths.\n * @returns Promise containing Result with the ZipFileTreeAccessors instance.\n */\n public static async fromBufferAsync<TCT extends string = string>(\n zipBuffer: ArrayBuffer | Uint8Array,\n prefix?: string\n ): Promise<Result<ZipFileTreeAccessors<TCT>>>;\n\n /**\n * Creates a new ZipFileTreeAccessors instance from a ZIP file buffer (asynchronous).\n * @param zipBuffer - The ZIP file as an ArrayBuffer or Uint8Array.\n * @param params - Optional initialization parameters.\n * @returns Promise containing Result with the ZipFileTreeAccessors instance.\n */\n public static async fromBufferAsync<TCT extends string = string>(\n zipBuffer: ArrayBuffer | Uint8Array,\n params?: FileTree.IFileTreeInitParams<TCT>\n ): Promise<Result<ZipFileTreeAccessors<TCT>>>;\n\n public static async fromBufferAsync<TCT extends string = string>(\n zipBuffer: ArrayBuffer | Uint8Array,\n params?: FileTree.IFileTreeInitParams<TCT> | string\n ): Promise<Result<ZipFileTreeAccessors<TCT>>> {\n return new Promise((resolve) => {\n try {\n /* c8 ignore next 1 - defense in depth */\n const uint8Buffer = zipBuffer instanceof Uint8Array ? zipBuffer : new Uint8Array(zipBuffer);\n unzip(uint8Buffer, (err, files) => {\n if (err) {\n resolve(fail(`Failed to load ZIP archive: ${err.message}`));\n } else {\n const normalizedParams = typeof params === 'string' ? { prefix: params } : params;\n resolve(succeed(new ZipFileTreeAccessors<TCT>(files, normalizedParams)));\n }\n });\n /* c8 ignore next 5 - defensive coding: fflate reports errors via callback, not exceptions */\n } catch (error) {\n resolve(\n fail(`Failed to load ZIP archive: ${error instanceof Error ? error.message : String(error)}`)\n );\n }\n });\n }\n\n /**\n * Creates a new ZipFileTreeAccessors instance from a File object (browser environment).\n * @param file - The File object containing ZIP data.\n * @param params - Optional initialization parameters.\n * @returns Result containing the ZipFileTreeAccessors instance.\n */\n public static async fromFile<TCT extends string = string>(\n file: File,\n params?: FileTree.IFileTreeInitParams<TCT>\n ): Promise<Result<ZipFileTreeAccessors<TCT>>> {\n try {\n const arrayBuffer = await file.arrayBuffer();\n const uint8Buffer = new Uint8Array(arrayBuffer);\n\n return await ZipFileTreeAccessors.fromBufferAsync<TCT>(uint8Buffer, params);\n } catch (error) {\n return fail(`Failed to read file: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n /**\n * Builds the cache of all items in the ZIP archive.\n */\n private _buildItemCache(): void {\n const directories = new Set<string>();\n\n // Process all files and collect directory paths\n for (const [relativePath, fileData] of Object.entries(this._files)) {\n // Skip directories in fflate output (they have null data)\n /* c8 ignore next 5 - handles explicit directory entries from external ZIP tools (fflate doesn't create these) */\n if (fileData === null || fileData === undefined) {\n const dirPath = relativePath.replace(/\\/$/, '');\n if (dirPath) {\n directories.add(dirPath);\n }\n } else {\n // Extract directory paths from file paths\n const pathParts = relativePath.split('/');\n for (let i = 1; i < pathParts.length; i++) {\n const dirPath = pathParts.slice(0, i).join('/');\n if (dirPath) {\n directories.add(dirPath);\n }\n }\n\n // Add the file item with its contents\n const absolutePath = this.resolveAbsolutePath(relativePath);\n const contents = new TextDecoder().decode(fileData);\n const item = new ZipFileItem<TCT>(relativePath, contents, this);\n this._itemCache.set(absolutePath, item);\n }\n }\n\n // Add directory items to cache\n directories.forEach((dirPath) => {\n const absolutePath = this.resolveAbsolutePath(dirPath);\n const item = new ZipDirectoryItem<TCT>(dirPath, this);\n this._itemCache.set(absolutePath, item);\n });\n }\n\n /**\n * Resolves paths to an absolute path.\n */\n public resolveAbsolutePath(...paths: string[]): string {\n const joinedPath = this.joinPaths(...paths);\n const prefixed = this._prefix ? this.joinPaths(this._prefix, joinedPath) : joinedPath;\n return prefixed.startsWith('/') ? prefixed : '/' + prefixed;\n }\n\n /**\n * Gets the extension of a path.\n */\n public getExtension(path: string): string {\n const name = this.getBaseName(path);\n const lastDotIndex = name.lastIndexOf('.');\n return lastDotIndex >= 0 ? name.substring(lastDotIndex) : '';\n }\n\n /**\n * Gets the base name of a path.\n */\n public getBaseName(path: string, suffix?: string): string {\n const normalizedPath = path.replace(/\\/$/, ''); // Remove trailing slash\n const parts = normalizedPath.split('/');\n let baseName = parts[parts.length - 1] || '';\n\n if (suffix && baseName.endsWith(suffix)) {\n baseName = baseName.substring(0, baseName.length - suffix.length);\n }\n\n return baseName;\n }\n\n /**\n * Joins paths together.\n */\n public joinPaths(...paths: string[]): string {\n return paths\n .filter((p) => p && p.length > 0)\n .map((p) => p.replace(/^\\/+|\\/+$/g, '')) // Remove leading/trailing slashes\n .join('/')\n .replace(/\\/+/g, '/'); // Normalize multiple slashes\n }\n\n /**\n * Gets an item from the file tree.\n */\n public getItem(path: string): Result<FileTree.FileTreeItem<TCT>> {\n const absolutePath = this.resolveAbsolutePath(path);\n const item = this._itemCache.get(absolutePath);\n\n if (item) {\n return succeed(item);\n }\n\n return fail(`Item not found: ${absolutePath}`);\n }\n\n /**\n * Gets the contents of a file in the file tree.\n */\n public getFileContents(path: string): Result<string> {\n return this.getItem(path).onSuccess((item) => {\n if (item.type !== 'file') {\n return fail(`Path is not a file: ${path}`);\n }\n return item.getRawContents();\n });\n }\n\n /**\n * Gets the content type of a file in the file tree.\n */\n public getFileContentType(path: string, provided?: string): Result<TCT | undefined> {\n // If provided contentType is given, use it directly (highest priority)\n if (provided !== undefined) {\n return succeed(provided as TCT);\n }\n\n // For files that exist in the ZIP, we don't store explicit contentType\n // so we always fall back to inference\n return this._inferContentType(path);\n }\n\n /**\n * Gets the children of a directory in the file tree.\n */\n public getChildren(path: string): Result<ReadonlyArray<FileTree.FileTreeItem<TCT>>> {\n const absolutePath = this.resolveAbsolutePath(path);\n const children: FileTree.FileTreeItem<TCT>[] = [];\n\n // Find all items that are direct children of this directory\n for (const [itemPath, item] of this._itemCache) {\n if (this._isDirectChild(absolutePath, itemPath)) {\n children.push(item);\n }\n }\n\n return succeed(children);\n }\n\n /**\n * Checks if childPath is a direct child of parentPath.\n */\n private _isDirectChild(parentPath: string, childPath: string): boolean {\n // Normalize paths\n const normalizedParent = parentPath.replace(/\\/$/, '');\n const normalizedChild = childPath.replace(/\\/$/, '');\n\n // Child must start with parent path\n if (!normalizedChild.startsWith(normalizedParent + '/')) {\n return false;\n }\n\n // Get the relative path from parent to child\n const relativePath = normalizedChild.substring(normalizedParent.length + 1);\n\n // Direct child means no additional slashes in the relative path\n return !relativePath.includes('/');\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"zipFileTreeAccessors.js","sourceRoot":"","sources":["../../../src/packlets/zip-file-tree/zipFileTreeAccessors.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2025 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { unzipSync, unzip, Unzipped } from 'fflate';\nimport { Result, succeed, fail, captureResult, Converter, Validator } from '@fgv/ts-utils';\nimport { FileTree, JsonValue } from '@fgv/ts-json-base';\n\n/**\n * Implementation of `FileTree.IFileTreeFileItem` for files in a ZIP archive.\n * ZIP files are read-only, so this item does not support mutation.\n * Use {@link FileTree.isMutableFileItem | isMutableFileItem} to check before attempting mutations.\n *\n * @remarks\n * ZIP entries are byte-native, so this item also implements the read half of the\n * optional binary capability (`FileTree.IBinaryFileTreeFileItem`) — use\n * `FileTree.isBinaryFileItem` to narrow and `getRawBytes()` to read the entry's\n * undecoded bytes.\n * @public\n */\nexport class ZipFileItem<TCT extends string = string> implements FileTree.IBinaryFileTreeFileItem<TCT> {\n /**\n * Indicates that this `FileTree.FileTreeItem` is a file.\n */\n public readonly type: 'file' = 'file';\n\n /**\n * The absolute path of the file within the ZIP archive.\n */\n public readonly absolutePath: string;\n\n /**\n * The name of the file\n */\n public readonly name: string;\n\n /**\n * The base name of the file (without extension)\n */\n public readonly baseName: string;\n\n /**\n * The extension of the file\n */\n public readonly extension: string;\n\n /**\n * The content type of the file.\n */\n public get contentType(): TCT | undefined {\n if (this._contentType === undefined && this._shouldInferContentType) {\n this._contentType = this._accessors.getFileContentType(this.absolutePath).orDefault();\n this._shouldInferContentType = false;\n }\n return this._contentType;\n }\n\n /**\n * The pre-loaded raw bytes of the ZIP entry.\n */\n private readonly _bytes: Uint8Array;\n\n /**\n * Text form of the entry, decoded lazily from the raw bytes on first text read.\n */\n private _contents: string | undefined;\n\n /**\n * The ZIP file tree accessors that created this item.\n */\n private readonly _accessors: ZipFileTreeAccessors<TCT>;\n\n /**\n * Mutable content type of the file.\n */\n private _contentType: TCT | undefined;\n\n /**\n * Flag to track if content type should be inferred on first access.\n */\n private _shouldInferContentType: boolean = true;\n\n /**\n * Constructor for ZipFileItem.\n * @param zipFilePath - The path of the file within the ZIP.\n * @param contents - The pre-loaded contents of the entry, either as raw bytes or as\n * already-decoded text. Text is encoded as UTF-8 for the byte accessor and is also\n * retained verbatim, so supplying text never round-trips through a decode.\n * @param accessors - The ZIP file tree accessors.\n */\n public constructor(\n zipFilePath: string,\n contents: string | Uint8Array,\n accessors: ZipFileTreeAccessors<TCT>\n ) {\n if (typeof contents === 'string') {\n this._contents = contents;\n this._bytes = new TextEncoder().encode(contents);\n } else {\n this._bytes = contents;\n }\n this._accessors = accessors;\n this.absolutePath = '/' + zipFilePath;\n this.name = accessors.getBaseName(zipFilePath);\n this.extension = accessors.getExtension(zipFilePath);\n this.baseName = accessors.getBaseName(zipFilePath, this.extension);\n }\n\n /**\n * Sets the content type of the file.\n * @param contentType - The content type of the file.\n */\n public setContentType(contentType: TCT | undefined): void {\n this._contentType = contentType;\n this._shouldInferContentType = false;\n }\n\n /**\n * Gets the contents of the file as parsed JSON.\n */\n public getContents(): Result<JsonValue>;\n public getContents<T>(converter: Validator<T> | Converter<T>): Result<T>;\n public getContents<T>(converter?: Validator<T> | Converter<T>): Result<T | JsonValue> {\n return this.getRawContents()\n .onSuccess((contents) => {\n return captureResult(() => JSON.parse(contents))\n .onSuccess((parsed) => {\n if (converter) {\n return converter.convert(parsed) as Result<T | JsonValue>;\n }\n return succeed(parsed as JsonValue);\n })\n .onFailure(() => {\n return fail(`Failed to parse JSON from file: ${this.absolutePath}`);\n });\n })\n .onFailure((error) => {\n return fail(`Failed to get contents from file: ${error}`);\n });\n }\n\n /**\n * Gets the raw contents of the file as a string.\n *\n * @remarks\n * The entry's bytes are decoded as UTF-8 with the lenient WHATWG default, so\n * malformed input is silently replaced with U+FFFD. Use `getRawBytes()` for the\n * undecoded bytes — and `new TextDecoder('utf-8', { fatal: true }).decode(bytes)`\n * for a decode that fails loudly instead.\n */\n public getRawContents(): Result<string> {\n if (this._contents === undefined) {\n this._contents = new TextDecoder().decode(this._bytes);\n }\n return succeed(this._contents);\n }\n\n /**\n * Gets the raw bytes of the ZIP entry, with no text decoding applied.\n *\n * @remarks\n * The returned array is the item's internal buffer and must not be modified.\n */\n public getRawBytes(): Result<Uint8Array> {\n return succeed(this._bytes);\n }\n}\n\n/**\n * Implementation of `IFileTreeDirectoryItem` for directories in a ZIP archive.\n * @public\n */\nexport class ZipDirectoryItem<TCT extends string = string> implements FileTree.IFileTreeDirectoryItem<TCT> {\n /**\n * Indicates that this `FileTree.FileTreeItem` is a directory.\n */\n public readonly type: 'directory' = 'directory';\n\n /**\n * The absolute path of the directory within the ZIP archive.\n */\n public readonly absolutePath: string;\n\n /**\n * The name of the directory\n */\n public readonly name: string;\n\n /**\n * The ZIP file tree accessors that created this item.\n */\n private readonly _accessors: ZipFileTreeAccessors<TCT>;\n\n /**\n * Constructor for ZipDirectoryItem.\n * @param directoryPath - The path of the directory within the ZIP.\n * @param accessors - The ZIP file tree accessors.\n */\n public constructor(directoryPath: string, accessors: ZipFileTreeAccessors<TCT>) {\n this._accessors = accessors;\n this.absolutePath = '/' + directoryPath.replace(/\\/$/, ''); // Normalize path\n this.name = accessors.getBaseName(directoryPath);\n }\n\n /**\n * Gets the children of the directory.\n */\n public getChildren(): Result<ReadonlyArray<FileTree.FileTreeItem<TCT>>> {\n return this._accessors.getChildren(this.absolutePath);\n }\n}\n\n/**\n * Read-only file tree accessors for ZIP archives.\n * ZIP archives are read-only by design — use {@link FileTree.isMutableAccessors | isMutableAccessors}\n * to check before attempting mutations.\n *\n * @remarks\n * ZIP entries are byte-native, so these accessors also implement the read half of the\n * optional binary capability (`FileTree.IBinaryFileTreeAccessors`) — use\n * `FileTree.isBinaryAccessors` to narrow and `getFileBytes()` to read an entry's\n * undecoded bytes.\n * @public\n */\nexport class ZipFileTreeAccessors<TCT extends string = string>\n implements FileTree.IBinaryFileTreeAccessors<TCT>\n{\n /**\n * The unzipped file data.\n */\n private readonly _files: Unzipped;\n\n /**\n * Optional prefix to prepend to paths.\n */\n private readonly _prefix: string;\n\n /**\n * Content type inference function.\n */\n private readonly _inferContentType: FileTree.ContentTypeFactory<TCT>;\n\n /**\n * Cache of all items in the ZIP for efficient lookups.\n */\n private readonly _itemCache: Map<string, FileTree.FileTreeItem<TCT>> = new Map();\n\n /**\n * Constructor for ZipFileTreeAccessors.\n * @param files - The unzipped file data from fflate.\n * @param params - Optional initialization parameters.\n */\n private constructor(files: Unzipped, params?: FileTree.IFileTreeInitParams<TCT>) {\n this._files = files;\n this._prefix = params?.prefix || '';\n this._inferContentType = params?.inferContentType ?? ZipFileTreeAccessors.defaultInferContentType;\n this._buildItemCache();\n }\n\n /**\n * Default function to infer the content type of a file.\n * @param __filePath - The path of the file.\n * @param __provided - Optional supplied content type.\n * @returns `Success` with the content type of the file if successful, or\n * `Failure` with an error message otherwise.\n * @remarks This default implementation always returns `Success` with `undefined`.\n * @public\n */\n public static defaultInferContentType<TCT extends string = string>(\n __filePath: string,\n __provided?: string\n ): Result<TCT | undefined> {\n return succeed(undefined);\n }\n\n /**\n * Creates a new ZipFileTreeAccessors instance from a ZIP file buffer (synchronous).\n * @param zipBuffer - The ZIP file as an ArrayBuffer or Uint8Array.\n * @param prefix - Optional prefix to prepend to paths.\n * @returns Result containing the ZipFileTreeAccessors instance.\n */\n public static fromBuffer<TCT extends string = string>(\n zipBuffer: ArrayBuffer | Uint8Array,\n prefix?: string\n ): Result<ZipFileTreeAccessors<TCT>>;\n\n /**\n * Creates a new ZipFileTreeAccessors instance from a ZIP file buffer (synchronous).\n * @param zipBuffer - The ZIP file as an ArrayBuffer or Uint8Array.\n * @param params - Optional initialization parameters.\n * @returns Result containing the ZipFileTreeAccessors instance.\n */\n public static fromBuffer<TCT extends string = string>(\n zipBuffer: ArrayBuffer | Uint8Array,\n params?: FileTree.IFileTreeInitParams<TCT>\n ): Result<ZipFileTreeAccessors<TCT>>;\n\n public static fromBuffer<TCT extends string = string>(\n zipBuffer: ArrayBuffer | Uint8Array,\n params?: FileTree.IFileTreeInitParams<TCT> | string\n ): Result<ZipFileTreeAccessors<TCT>> {\n try {\n /* c8 ignore next 1 - defense in depth */\n const uint8Buffer = zipBuffer instanceof Uint8Array ? zipBuffer : new Uint8Array(zipBuffer);\n const files = unzipSync(uint8Buffer);\n const normalizedParams = typeof params === 'string' ? { prefix: params } : params;\n return succeed(new ZipFileTreeAccessors<TCT>(files, normalizedParams));\n } catch (error) {\n /* c8 ignore next 1 - defensive coding: fflate always throws Error objects in practice */\n return fail(`Failed to load ZIP archive: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n /**\n * Creates a new ZipFileTreeAccessors instance from a ZIP file buffer (asynchronous).\n * @param zipBuffer - The ZIP file as an ArrayBuffer or Uint8Array.\n * @param prefix - Optional prefix to prepend to paths.\n * @returns Promise containing Result with the ZipFileTreeAccessors instance.\n */\n public static async fromBufferAsync<TCT extends string = string>(\n zipBuffer: ArrayBuffer | Uint8Array,\n prefix?: string\n ): Promise<Result<ZipFileTreeAccessors<TCT>>>;\n\n /**\n * Creates a new ZipFileTreeAccessors instance from a ZIP file buffer (asynchronous).\n * @param zipBuffer - The ZIP file as an ArrayBuffer or Uint8Array.\n * @param params - Optional initialization parameters.\n * @returns Promise containing Result with the ZipFileTreeAccessors instance.\n */\n public static async fromBufferAsync<TCT extends string = string>(\n zipBuffer: ArrayBuffer | Uint8Array,\n params?: FileTree.IFileTreeInitParams<TCT>\n ): Promise<Result<ZipFileTreeAccessors<TCT>>>;\n\n public static async fromBufferAsync<TCT extends string = string>(\n zipBuffer: ArrayBuffer | Uint8Array,\n params?: FileTree.IFileTreeInitParams<TCT> | string\n ): Promise<Result<ZipFileTreeAccessors<TCT>>> {\n return new Promise((resolve) => {\n try {\n /* c8 ignore next 1 - defense in depth */\n const uint8Buffer = zipBuffer instanceof Uint8Array ? zipBuffer : new Uint8Array(zipBuffer);\n unzip(uint8Buffer, (err, files) => {\n if (err) {\n resolve(fail(`Failed to load ZIP archive: ${err.message}`));\n } else {\n const normalizedParams = typeof params === 'string' ? { prefix: params } : params;\n resolve(succeed(new ZipFileTreeAccessors<TCT>(files, normalizedParams)));\n }\n });\n /* c8 ignore next 5 - defensive coding: fflate reports errors via callback, not exceptions */\n } catch (error) {\n resolve(\n fail(`Failed to load ZIP archive: ${error instanceof Error ? error.message : String(error)}`)\n );\n }\n });\n }\n\n /**\n * Creates a new ZipFileTreeAccessors instance from a File object (browser environment).\n * @param file - The File object containing ZIP data.\n * @param params - Optional initialization parameters.\n * @returns Result containing the ZipFileTreeAccessors instance.\n */\n public static async fromFile<TCT extends string = string>(\n file: File,\n params?: FileTree.IFileTreeInitParams<TCT>\n ): Promise<Result<ZipFileTreeAccessors<TCT>>> {\n try {\n const arrayBuffer = await file.arrayBuffer();\n const uint8Buffer = new Uint8Array(arrayBuffer);\n\n return await ZipFileTreeAccessors.fromBufferAsync<TCT>(uint8Buffer, params);\n } catch (error) {\n return fail(`Failed to read file: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n /**\n * Builds the cache of all items in the ZIP archive.\n */\n private _buildItemCache(): void {\n const directories = new Set<string>();\n\n // Process all files and collect directory paths\n for (const [relativePath, fileData] of Object.entries(this._files)) {\n // Skip directories in fflate output (they have null data)\n /* c8 ignore next 5 - handles explicit directory entries from external ZIP tools (fflate doesn't create these) */\n if (fileData === null || fileData === undefined) {\n const dirPath = relativePath.replace(/\\/$/, '');\n if (dirPath) {\n directories.add(dirPath);\n }\n } else {\n // Extract directory paths from file paths\n const pathParts = relativePath.split('/');\n for (let i = 1; i < pathParts.length; i++) {\n const dirPath = pathParts.slice(0, i).join('/');\n if (dirPath) {\n directories.add(dirPath);\n }\n }\n\n // Add the file item with its raw bytes; text is decoded lazily on demand.\n const absolutePath = this.resolveAbsolutePath(relativePath);\n const item = new ZipFileItem<TCT>(relativePath, fileData, this);\n this._itemCache.set(absolutePath, item);\n }\n }\n\n // Add directory items to cache\n directories.forEach((dirPath) => {\n const absolutePath = this.resolveAbsolutePath(dirPath);\n const item = new ZipDirectoryItem<TCT>(dirPath, this);\n this._itemCache.set(absolutePath, item);\n });\n }\n\n /**\n * Resolves paths to an absolute path.\n */\n public resolveAbsolutePath(...paths: string[]): string {\n const joinedPath = this.joinPaths(...paths);\n const prefixed = this._prefix ? this.joinPaths(this._prefix, joinedPath) : joinedPath;\n return prefixed.startsWith('/') ? prefixed : '/' + prefixed;\n }\n\n /**\n * Gets the extension of a path.\n */\n public getExtension(path: string): string {\n const name = this.getBaseName(path);\n const lastDotIndex = name.lastIndexOf('.');\n return lastDotIndex >= 0 ? name.substring(lastDotIndex) : '';\n }\n\n /**\n * Gets the base name of a path.\n */\n public getBaseName(path: string, suffix?: string): string {\n const normalizedPath = path.replace(/\\/$/, ''); // Remove trailing slash\n const parts = normalizedPath.split('/');\n let baseName = parts[parts.length - 1] || '';\n\n if (suffix && baseName.endsWith(suffix)) {\n baseName = baseName.substring(0, baseName.length - suffix.length);\n }\n\n return baseName;\n }\n\n /**\n * Joins paths together.\n */\n public joinPaths(...paths: string[]): string {\n return paths\n .filter((p) => p && p.length > 0)\n .map((p) => p.replace(/^\\/+|\\/+$/g, '')) // Remove leading/trailing slashes\n .join('/')\n .replace(/\\/+/g, '/'); // Normalize multiple slashes\n }\n\n /**\n * Gets an item from the file tree.\n */\n public getItem(path: string): Result<FileTree.FileTreeItem<TCT>> {\n const absolutePath = this.resolveAbsolutePath(path);\n const item = this._itemCache.get(absolutePath);\n\n if (item) {\n return succeed(item);\n }\n\n return fail(`Item not found: ${absolutePath}`);\n }\n\n /**\n * Gets the contents of a file in the file tree.\n *\n * @remarks\n * The entry's bytes are decoded as UTF-8 with the lenient WHATWG default. Use\n * `getFileBytes()` for the undecoded bytes.\n */\n public getFileContents(path: string): Result<string> {\n return this._getFileItem(path).onSuccess((item) => item.getRawContents());\n }\n\n /**\n * Gets the raw bytes of a ZIP entry, with no text decoding applied.\n *\n * @remarks\n * The returned array is the archive's internal buffer and must not be modified.\n */\n public getFileBytes(path: string): Result<Uint8Array> {\n return this._getFileItem(path).onSuccess((item) => item.getRawBytes());\n }\n\n /**\n * Resolves a path to the ZIP file item it names.\n * @param path - Path of the entry to look up.\n * @returns `Success` with the item, or `Failure` if it is missing or is a directory.\n */\n private _getFileItem(path: string): Result<ZipFileItem<TCT>> {\n return this.getItem(path).onSuccess((item) => {\n if (!(item instanceof ZipFileItem)) {\n return fail(`Path is not a file: ${path}`);\n }\n return succeed(item);\n });\n }\n\n /**\n * Gets the content type of a file in the file tree.\n */\n public getFileContentType(path: string, provided?: string): Result<TCT | undefined> {\n // If provided contentType is given, use it directly (highest priority)\n if (provided !== undefined) {\n return succeed(provided as TCT);\n }\n\n // For files that exist in the ZIP, we don't store explicit contentType\n // so we always fall back to inference\n return this._inferContentType(path);\n }\n\n /**\n * Gets the children of a directory in the file tree.\n */\n public getChildren(path: string): Result<ReadonlyArray<FileTree.FileTreeItem<TCT>>> {\n const absolutePath = this.resolveAbsolutePath(path);\n const children: FileTree.FileTreeItem<TCT>[] = [];\n\n // Find all items that are direct children of this directory\n for (const [itemPath, item] of this._itemCache) {\n if (this._isDirectChild(absolutePath, itemPath)) {\n children.push(item);\n }\n }\n\n return succeed(children);\n }\n\n /**\n * Checks if childPath is a direct child of parentPath.\n */\n private _isDirectChild(parentPath: string, childPath: string): boolean {\n // Normalize paths\n const normalizedParent = parentPath.replace(/\\/$/, '');\n const normalizedChild = childPath.replace(/\\/$/, '');\n\n // Child must start with parent path\n if (!normalizedChild.startsWith(normalizedParent + '/')) {\n return false;\n }\n\n // Get the relative path from parent to child\n const relativePath = normalizedChild.substring(normalizedParent.length + 1);\n\n // Direct child means no additional slashes in the relative path\n return !relativePath.includes('/');\n }\n}\n"]}
|
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
import { Result } from '@fgv/ts-utils';
|
|
2
2
|
/**
|
|
3
|
-
* Simple interface for a file to be added to a zip file.
|
|
3
|
+
* Simple interface for a text file to be added to a zip file.
|
|
4
4
|
* @public
|
|
5
5
|
*/
|
|
6
6
|
export interface IZipTextFile {
|
|
7
7
|
readonly path: string;
|
|
8
8
|
readonly contents: string;
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Interface for a file to be added to a zip file, whose contents are either text or
|
|
12
|
+
* raw bytes.
|
|
13
|
+
*
|
|
14
|
+
* @remarks
|
|
15
|
+
* String contents are encoded as UTF-8; `Uint8Array` contents are stored verbatim.
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
export interface IZipFile {
|
|
19
|
+
readonly path: string;
|
|
20
|
+
readonly contents: string | Uint8Array;
|
|
21
|
+
}
|
|
10
22
|
/**
|
|
11
23
|
* Supported compression levels for zip files.
|
|
12
24
|
* @public
|
|
@@ -21,7 +33,20 @@ export interface ICreateZipOptions {
|
|
|
21
33
|
}
|
|
22
34
|
/**
|
|
23
35
|
* Creates a zip file from an array of text files.
|
|
36
|
+
*
|
|
37
|
+
* @remarks
|
|
38
|
+
* Contents are encoded as UTF-8. Use `createZipFromFiles` to write entries whose
|
|
39
|
+
* contents are raw bytes.
|
|
24
40
|
* @public
|
|
25
41
|
*/
|
|
26
42
|
export declare function createZipFromTextFiles(files: ReadonlyArray<IZipTextFile>, options?: ICreateZipOptions): Result<Uint8Array>;
|
|
43
|
+
/**
|
|
44
|
+
* Creates a zip file from an array of files whose contents are either text or raw bytes.
|
|
45
|
+
*
|
|
46
|
+
* @remarks
|
|
47
|
+
* String contents are encoded as UTF-8; `Uint8Array` contents are stored verbatim, so
|
|
48
|
+
* arbitrary binary payloads round-trip through the archive unchanged.
|
|
49
|
+
* @public
|
|
50
|
+
*/
|
|
51
|
+
export declare function createZipFromFiles(files: ReadonlyArray<IZipFile>, options?: ICreateZipOptions): Result<Uint8Array>;
|
|
27
52
|
//# sourceMappingURL=zipFileTreeWriter.d.ts.map
|