Skip to content

feat: enhance generate:metadata-payload with mode filtering, path targeting, and CI/lint-staged integration#3788

Open
itsarijitray wants to merge 14 commits into
mainfrom
feat/metadata-payload-cli-enhancements
Open

feat: enhance generate:metadata-payload with mode filtering, path targeting, and CI/lint-staged integration#3788
itsarijitray wants to merge 14 commits into
mainfrom
feat/metadata-payload-cli-enhancements

Conversation

@itsarijitray
Copy link
Copy Markdown
Contributor

@itsarijitray itsarijitray commented May 13, 2026

Summary

Comprehensive enhancements to the generate:metadata-payload CLI command:

  • --mode flag (-m): Filter metadata generation by destination mode (cloud, device, warehouse)
  • --path flag (-p): Generate metadata only for destinations matching given file paths — enables efficient targeted regeneration from lint-staged
  • Unregistered destination discovery: Scans the filesystem for destinations not registered in index.ts, so metadata.json can be generated for WIP destinations
  • Warehouse destination support: Discovers and generates metadata for warehouse destinations in packages/warehouse-destinations/
  • Lint-staged pre-commit hook: Automatically regenerates and stages metadata.json when destination source files are modified
  • CI validation step: Fails the build if any metadata.json is stale (runs full generation and checks for uncommitted diffs)
  • Enhanced serialization: Includes syncMode, hooks (with inputFields/outputFields), audienceConfig (discriminated union mode), and all field properties (hidden, readOnly, minimum, maximum, defaultObjectUI, disabledInputMethods, displayMode, additionalProperties)
  • Deep review fixes: Proper outputTypes ?? outputFields fallback for hooks, discriminated union for audienceConfig mode, robust hookTypeStrings filtering

New files

  • scripts/update-metadata-payload.sh — called by lint-staged to regenerate affected destinations' metadata
  • scripts/assert-metadata-payload.sh — CI script that asserts no stale metadata.json files

Modified files

  • packages/cli/src/commands/generate/metadata-payload.ts--mode, --path flags, extractDestinationDirs(), filesystem discovery
  • .github/workflows/ci.yml — new validate step
  • package.json — lint-staged config for metadata regeneration
  • packages/cli/src/__tests__/generate-metadata-payload.test.ts — 63+ test cases covering all features

Test plan

  • ./bin/run generate:metadata-payload --mode=cloud generates only cloud destinations
  • ./bin/run generate:metadata-payload --path packages/destination-actions/src/destinations/amplitude generates only amplitude
  • Unregistered destinations discovered from filesystem
  • Warehouse destinations discovered and processed
  • --slug flag still works
  • TypeScript compiles cleanly
  • lint-staged hook triggers update-metadata-payload.sh and stages metadata.json
  • CI assert-metadata-payload.sh checks cloud, browser, and warehouse metadata staleness

🤖 Generated with Claude Code

…ate:metadata-payload

Adds a --mode flag to filter metadata generation by destination mode (cloud/device),
and discovers unregistered cloud destinations from the filesystem so they can also
have their metadata.json generated without being registered in index.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 13, 2026 06:24
@itsarijitray itsarijitray requested a review from a team as a code owner May 13, 2026 06:24
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enhances the CLI generate:metadata-payload command to better support generating metadata.json during development/CI by adding mode-based filtering and discovering cloud destinations that exist on disk but aren’t yet registered in the destination-actions manifest.

Changes:

  • Added a --mode/-m flag to filter generated metadata by destination mode (e.g., cloud, device).
  • Added filesystem discovery for unregistered cloud destinations under packages/destination-actions/src/destinations and includes them in the generation run.
  • Updated command examples to document the new flag.

Comment on lines +312 to +316
// Discover unregistered cloud destinations from the filesystem
const cloudDestDir = path.join(process.cwd(), 'packages', 'destination-actions', 'src', 'destinations')
const registeredDirs = new Set(Object.values(manifest).map((entry: any) => entry.directory as string))

if (await fs.pathExists(cloudDestDir)) {
Comment thread packages/cli/src/commands/generate/metadata-payload.ts Outdated
Comment thread packages/cli/src/commands/generate/metadata-payload.ts Outdated
Comment thread packages/cli/src/commands/generate/metadata-payload.ts Outdated
Discovers warehouse destinations from packages/warehouse-destinations/src/destinations/
and generates metadata.json for them. Handles the warehouse-specific settings field
and resolveSourceDir patterns. Updates --mode flag to accept 'warehouse'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 13, 2026 06:40
@itsarijitray itsarijitray force-pushed the feat/metadata-payload-cli-enhancements branch from e783ec8 to 1c246dd Compare May 13, 2026 06:40
Adds convenience scripts for generating metadata by destination mode:
- generate:metadata-payload:cloud
- generate:metadata-payload:browser
- generate:metadata-payload:warehouse

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

packages/cli/src/commands/generate/metadata-payload.ts:400

  • When --mode is provided and nothing matches, the command currently exits successfully after generating 0 files. It would be more consistent with the existing --slug behavior to throw an error when filterModes is set but generated === 0, so invalid/unsupported mode values are surfaced in CI.
      if (filterModes && filterModes.length > 0) {
        const definitionMode = ((definition as any).mode ?? 'cloud') as string
        if (!filterModes.includes(definitionMode)) {
          skipped++
          continue

Comment on lines +338 to +343
if (await fs.pathExists(cloudDestDir)) {
const dirs = await fs.readdir(cloudDestDir)
for (const dir of dirs) {
if (registeredDirs.has(dir)) continue
const indexPath = path.join(cloudDestDir, dir, 'index.ts')
if (!(await fs.pathExists(indexPath))) continue
Comment thread packages/cli/src/commands/generate/metadata-payload.ts Outdated
itsarijitray and others added 2 commits May 13, 2026 16:12
…nceConfig details

Adds missing fields to generated metadata.json that the bot service needs:
- syncMode label/description/choices on actions
- hooks inputFields/outputFields
- displayMode, additionalProperties on action fields
- audienceConfig.supportsAudienceFunctions
- multiple/depends_on on auth fields

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use flags.enum for --mode to validate values and fail fast on typos
- Filter registeredDirs to only cloud-manifest entries to avoid
  false-positive skips when browser/cloud dir names collide
- Log skipped destination errors via this.debug() instead of silently
  swallowing them
- Update test mocks to include fs.pathExists and fs.readdir
- Add filesystem discovery tests covering: discovering unregistered
  destinations, skipping invalid folders, and ensuring discovered
  entries are written correctly

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 13, 2026 10:54
@itsarijitray
Copy link
Copy Markdown
Contributor Author

Deep Code Review

Bug Findings

# Severity Issue Location
1 Medium Warehouse discovery only skips index.ts files but not other non-directory entries (e.g., utils.ts, .DS_Store). While pathExists prevents crashes, it's wasteful and brittle. Should use readdir({ withFileTypes: true }) and filter to directories. metadata-payload.ts L422
2 Medium hook.outputTypes is read from source definitions but serialized as outputFields — naming mismatch is a maintenance trap if upstream renames. Should add fallback: hook.outputTypes ?? hook.outputFields ?? {}. metadata-payload.ts L194
3 Low audienceConfig.mode coerces to { type, full_audience_sync? } for all mode types, but full_audience_sync only exists on 'synced' variant. Outputs undefined for 'realtime' which JSON.stringify silently drops — acceptable but inconsistent. metadata-payload.ts L248-253
4 Low Mode filter defaults to 'cloud' for definitions missing a mode field, which could misclassify warehouse defs in older formats. metadata-payload.ts L455

Test Coverage Gaps

# Gap Suggested Test
1 No --mode filtering tests "filters to only cloud dests when --mode=cloud", "skips cloud when --mode=device"
2 No warehouse resolveSourceDir tests "resolves compiled warehouse dist path", "resolves warehouse src path"
3 No tests for displayMode, additionalProperties on action fields "serializes displayMode and additionalProperties"
4 No tests for multiple/depends_on on auth fields "serializes multiple and depends_on on auth fields"
5 No warehouse discovery tests "discovers warehouse destinations from filesystem"

Architecture Notes

# Severity Note
1 Medium registeredDirs uses string-contains check (entry.path?.includes('packages/destination-actions')) which is fragile. Consider using path.startsWith(cloudDestDir) or checking resolved paths.
2 Low Manifest is mutated in-place with synthetic IDs. A separate merged map would be safer if getManifest() ever returns a frozen object.
3 Low process.cwd() assumption for discovery paths is undocumented for warehouse. Acceptable given existing convention but worth noting.

🤖 Generated with Claude Code deep review (3 parallel reviewers)

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

packages/cli/src/commands/generate/metadata-payload.ts:461

  • New --mode filtering logic is added here, but the test suite only exercises --slug filtering. Add command-level tests to verify that --mode=cloud/device/warehouse includes only matching destinations (and that multiple --mode values behave as expected).
      if (filterModes && filterModes.length > 0) {
        const definitionMode = ((definition as any).mode ?? 'cloud') as string
        if (!filterModes.includes(definitionMode)) {
          skipped++
          continue
        }
      }

Comment on lines +389 to +427
// Discover unregistered cloud destinations from the filesystem
const cloudDestDir = path.join(process.cwd(), 'packages', 'destination-actions', 'src', 'destinations')
const registeredDirs = new Set(
Object.values(manifest)
.filter((entry: any) => entry.path?.includes('packages/destination-actions'))
.map((entry: any) => entry.directory as string)
)

if (await fs.pathExists(cloudDestDir)) {
const dirs = await fs.readdir(cloudDestDir)
for (const dir of dirs) {
if (registeredDirs.has(dir)) continue
const indexPath = path.join(cloudDestDir, dir, 'index.ts')
if (!(await fs.pathExists(indexPath))) continue
try {
const definition = await loadDestination(indexPath)
if (!definition) continue
manifest[`unregistered:${dir}`] = {
definition,
directory: dir,
path: indexPath
}
} catch (err) {
this.debug(`Skipping unregistered destination "${dir}": ${(err as Error).message}`)
}
}
}

// Discover warehouse destinations from the filesystem
const warehouseDestDir = path.join(process.cwd(), 'packages', 'warehouse-destinations', 'src', 'destinations')
if (await fs.pathExists(warehouseDestDir)) {
const dirs = await fs.readdir(warehouseDestDir)
for (const dir of dirs) {
if (dir === 'index.ts') continue
const indexPath = path.join(warehouseDestDir, dir, 'index.ts')
if (!(await fs.pathExists(indexPath))) continue
try {
const definition = await loadDestination(indexPath)
if (!definition) continue
Comment on lines +57 to +71
syncMode: {
default: string
label: string
description: string
choices: Array<{ label: string; value: string }>
} | null
hooks: Record<
string,
{
label: string
description: string
inputFields: Record<string, PublicActionField>
outputFields: Record<string, PublicActionField>
}
> | null
Comment on lines +323 to +337
// Compiled warehouse: .../packages/warehouse-destinations/dist/destinations/<name>/index.js
const warehouseDistMatch = entryPath.match(
/^(.+\/packages\/warehouse-destinations)\/dist\/destinations\/([^/]+)\/index\.js$/
)
if (warehouseDistMatch) {
return path.join(warehouseDistMatch[1], 'src', 'destinations', warehouseDistMatch[2])
}

// Source warehouse: .../packages/warehouse-destinations/src/destinations/<name>/index.ts
const warehouseSrcMatch = entryPath.match(
/^(.+\/packages\/warehouse-destinations\/src\/destinations\/[^/]+)\/index\.ts$/
)
if (warehouseSrcMatch) {
return warehouseSrcMatch[1]
}
itsarijitray and others added 2 commits May 13, 2026 16:33
Bug fixes:
- Use readdir({ withFileTypes: true }) to filter directories only,
  avoiding wasteful pathExists calls on non-directory entries
- Add fallback for hook.outputTypes → hook.outputFields naming
- Only include full_audience_sync in audienceConfig when mode is
  'synced' (proper discriminated union)
- Use path.startsWith check for registeredDirs filtering

Test improvements:
- Add --mode=cloud and --mode=device filtering tests
- Add warehouse resolveSourceDir path tests
- Add displayMode/additionalProperties action field tests
- Add multiple/depends_on auth field tests
- Add test for skipping non-directory entries
- Update discovery test mocks to use Dirent objects

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ta.json

Adds targeted metadata regeneration via --path flag so lint-staged can
efficiently regenerate only affected destinations' metadata.json on commit.
Also adds a CI validate step to assert metadata payloads stay up-to-date.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 14, 2026 06:26
@itsarijitray itsarijitray changed the title feat: add --mode flag and unregistered dest discovery to generate:metadata-payload feat: enhance generate:metadata-payload with mode filtering, path targeting, and CI/lint-staged integration May 14, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (2)

packages/cli/src/commands/generate/metadata-payload.ts:515

  • Filtering only against entry.directory misses merged cloud/browser manifest entries. For example the browser manifest registers packages/browser-destinations/destinations/amplitude-plugins under the same metadata ID as the cloud amplitude destination, and getManifest() keeps the cloud entry directory (amplitude) while merging the browser action into it. A --path from amplitude-plugins therefore skips the merged destination and won't regenerate the metadata file that contains that web action.
      if (filterDirs && filterDirs.size > 0) {
        const entryDir: string = entry.directory?.split('/').pop() ?? ''
        if (!filterDirs.has(entryDir)) {
          skipped++
          continue

packages/cli/src/commands/generate/metadata-payload.ts:515

  • The path filter compares only the destination directory basename, so paths from one package can match unrelated destinations in another package that happen to share the same directory name (for example browser braze and cloud braze). This makes --path over-generate metadata outside the changed destination; the filter needs to preserve package/mode context or match against source paths rather than just basenames.
      if (filterDirs && filterDirs.size > 0) {
        const entryDir: string = entry.directory?.split('/').pop() ?? ''
        if (!filterDirs.has(entryDir)) {
          skipped++
          continue

Comment thread scripts/assert-metadata-payload.sh Outdated
Comment on lines +57 to +71
syncMode: {
default: string
label: string
description: string
choices: Array<{ label: string; value: string }>
} | null
hooks: Record<
string,
{
label: string
description: string
inputFields: Record<string, PublicActionField>
outputFields: Record<string, PublicActionField>
}
> | null
Comment on lines +511 to +517
if (filterDirs && filterDirs.size > 0) {
const entryDir: string = entry.directory?.split('/').pop() ?? ''
if (!filterDirs.has(entryDir)) {
skipped++
continue
}
}
Comment on lines +464 to +485
// Discover warehouse destinations from the filesystem
const warehouseDestDir = path.join(process.cwd(), 'packages', 'warehouse-destinations', 'src', 'destinations')
if (await fs.pathExists(warehouseDestDir)) {
const entries = await fs.readdir(warehouseDestDir, { withFileTypes: true })
for (const entry of entries) {
if (!entry.isDirectory()) continue
const dir = entry.name
const indexPath = path.join(warehouseDestDir, dir, 'index.ts')
if (!(await fs.pathExists(indexPath))) continue
try {
const definition = await loadDestination(indexPath)
if (!definition) continue
manifest[`warehouse:${dir}`] = {
definition,
directory: dir,
path: indexPath
}
} catch (err) {
this.debug(`Skipping warehouse destination "${dir}": ${(err as Error).message}`)
}
}
}
Comment thread .github/workflows/ci.yml
Comment on lines +133 to +134
- name: Assert metadata payloads are up-to-date
run: bash scripts/assert-metadata-payload.sh
…warehouse tests

- --path with unrecognized paths now exits early instead of generating all
- CI assert script uses git diff (not git status) to ignore untracked files
- Added warehouse filesystem discovery tests with --mode filtering

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@itsarijitray
Copy link
Copy Markdown
Contributor Author

All Copilot review comments addressed

Here's a summary of how each concern was resolved:

Comment Resolution
No tests for filesystem discovery Added comprehensive tests: discovers unregistered dirs, skips non-dirs, skips missing index.ts, skips null/throwing loadDestination, does not re-discover registered dirs
--mode accepts arbitrary strings Changed to flags.enum with options: ['cloud', 'device', 'warehouse'] — oclif validates at parse time
Suppressed load errors in catch Already uses this.debug(...) with directory name and error message
registeredDirs includes browser dests Filter already scopes to entries whose path contains packages/destination-actions
Tests need fs.pathExists/readdir mocks Test mock already includes pathExists and readdir in the fs-extra mock
loadDestination on .ts in CI Not an issue — ./bin/run uses oclif which auto-registers ts-node; .ts files load fine via require()
PR description missing schema changes Updated PR description to document all schema changes
No warehouse resolveSourceDir tests Added tests for both compiled and source warehouse path patterns
CI assert fails on untracked files Changed to git diff --name-only which only checks tracked files for modifications
Schema contract changes undocumented Documented in PR description
--path empty set generates all Now exits early with message when no paths match known layouts
No warehouse discovery tests Added 3 tests: discovers warehouse dests, filters with --mode=warehouse, excludes with --mode=cloud
CI step fails for uncommitted metadata Fixed: git diff only flags tracked files that changed, not new untracked ones

Browser destinations registered in the manifest have entry paths under
node_modules/@segment/analytics-browser-*, which didn't match any
resolveSourceDir pattern. Added a lazy package.json lookup map that maps
package names back to source directories under browser-destinations/.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 14, 2026 09:38
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (5)

packages/cli/src/commands/generate/metadata-payload.ts:552

  • The path filter only compares the extracted directory name to entry.directory, which misses merged cloud+browser destinations. For example, a staged browser file under packages/browser-destinations/destinations/amplitude-plugins/... extracts amplitude-plugins, but getManifest() merges that browser action into the cloud manifest entry whose directory is amplitude, so --path generates nothing and leaves the cloud metadata stale.
      if (filterDirs && filterDirs.size > 0) {
        const entryDir: string = entry.directory?.split('/').pop() ?? ''
        if (!filterDirs.has(entryDir)) {

packages/cli/src/commands/generate/metadata-payload.ts:490

  • This passes a source .ts file to loadDestination, but the normal CLI entrypoint only registers tsconfig-paths and does not register ts-node; loadDestination uses require() directly. In CI/lint-staged this will fail to load TypeScript source files and silently skip unregistered destinations, so the new discovery path will not generate their metadata.
          const definition = await loadDestination(indexPath)

packages/cli/src/commands/generate/metadata-payload.ts:513

  • Warehouse discovery has the same source-loading problem: it passes index.ts to loadDestination, which uses plain require() without ts-node registered by bin/run. As a result, the CI command will skip warehouse destinations instead of generating their metadata.
          const definition = await loadDestination(indexPath)

packages/cli/src/commands/generate/metadata-payload.ts:552

  • The filter collapses paths to a bare destination directory name, so it cannot distinguish packages with the same basename. This repo has overlaps such as cloud braze and browser braze; passing a path for one will also generate and potentially stage metadata for the other, which defeats targeted regeneration and can add unrelated metadata files.
      if (filterDirs && filterDirs.size > 0) {
        const entryDir: string = entry.directory?.split('/').pop() ?? ''
        if (!filterDirs.has(entryDir)) {

packages/cli/src/commands/generate/metadata-payload.ts:544

  • Filtering solely on definition.mode does not work for destinations whose browser actions are merged into a cloud manifest entry by getManifest(). Those entries keep the cloud definition mode, so --mode=device will skip merged browser actions (for example Amplitude plugins), while --mode=cloud can still emit metadata containing web actions.
      if (filterModes && filterModes.length > 0) {
        const definitionMode = ((definition as any).mode ?? 'cloud') as string
        if (!filterModes.includes(definitionMode)) {

Comment on lines +8 to 12
# Only check already-tracked metadata.json files for modifications (ignore untracked)
STALE=$(git diff --name-only -- 'packages/destination-actions/src/destinations/*/metadata.json' 'packages/browser-destinations/destinations/*/metadata.json' 'packages/warehouse-destinations/src/destinations/*/metadata.json')

if [ -n "$STALE" ]; then
echo "The following metadata files are out of date:"
Comment on lines +117 to +120
multiple: schema.multiple ?? false,
choices: normalizeChoices(schema.choices),
default: schema.default ?? null
default: schema.default ?? null,
depends_on: schema.depends_on ?? null
Comment on lines +470 to +471
// Discover unregistered cloud destinations from the filesystem
const cloudDestDir = path.join(process.cwd(), 'packages', 'destination-actions', 'src', 'destinations')
Comment on lines +162 to 163
additionalProperties: field.additionalProperties ?? false
}
itsarijitray and others added 2 commits May 14, 2026 17:26
Ensures generated metadata.json always conforms to the repo's prettier
config by running prettier --write on all generated files after the
generation loop completes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 14, 2026 12:35
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 8 comments.

Comments suppressed due to low confidence (2)

packages/cli/src/commands/generate/metadata-payload.ts:189

  • This changes hooks from the previously emitted string array to an object/null shape without preserving the old list of hook names or versioning the metadata payload. Any consumer that currently checks hooks.includes(...) will fail after regeneration; consider retaining a compatible hook-name list while adding the detailed hook metadata.
  const hooks: PublicAction['hooks'] = {}
  if (action.hooks) {
    for (const [hookKey, hook] of Object.entries(action.hooks as Record<string, any>)) {
      if (!hookTypeStrings.includes(hookKey as any)) continue

packages/cli/src/commands/generate/metadata-payload.ts:179

  • This changes the serialized syncMode contract by removing the existing supportedModes array and replacing it with choices. Since metadata.json is a generated public payload and there is no schema version bump or compatibility field, existing consumers that read syncMode.supportedModes will break; keep the old field alongside the new metadata or introduce a versioned format.
    syncMode = {
      default: action.syncMode.default,
      label: action.syncMode.label ?? 'Sync Mode',
      description: action.syncMode.description ?? '',
      choices: (action.syncMode.choices ?? []).map((c: { value: string; label: string }) => ({

Comment on lines +8 to +9
# Only check already-tracked metadata.json files for modifications (ignore untracked)
STALE=$(git diff --name-only -- 'packages/destination-actions/src/destinations/*/metadata.json' 'packages/browser-destinations/destinations/*/metadata.json' 'packages/warehouse-destinations/src/destinations/*/metadata.json')
Comment on lines +471 to +472
// Discover unregistered cloud destinations from the filesystem
const cloudDestDir = path.join(process.cwd(), 'packages', 'destination-actions', 'src', 'destinations')
Comment on lines +511 to +514
const indexPath = path.join(warehouseDestDir, dir, 'index.ts')
if (!(await fs.pathExists(indexPath))) continue
try {
const definition = await loadDestination(indexPath)
Comment on lines +488 to +491
const indexPath = path.join(cloudDestDir, dir, 'index.ts')
if (!(await fs.pathExists(indexPath))) continue
try {
const definition = await loadDestination(indexPath)
label: 'Traits',
description: 'User traits.',
type: 'object',
displayMode: 'key-value',
Comment on lines +544 to +546
if (filterModes && filterModes.length > 0) {
const definitionMode = ((definition as any).mode ?? 'cloud') as string
if (!filterModes.includes(definitionMode)) {
Comment on lines +552 to +554
if (filterDirs && filterDirs.size > 0) {
const entryDir: string = entry.directory?.split('/').pop() ?? ''
if (!filterDirs.has(entryDir)) {
Comment on lines +156 to +157
readOnly: field.readOnly ?? null,
hidden: field.unsafe_hidden ?? null,
itsarijitray and others added 2 commits May 18, 2026 11:23
Instead of flattening conditional required fields to false, retain the
full conditions object so downstream consumers can evaluate them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When merging browser and cloud manifests, copy browser destination
settings into the cloud definition's authentication fields so metadata
generation captures both.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 18, 2026 07:44
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Comment on lines +8 to +9
# Only check already-tracked metadata.json files for modifications (ignore untracked)
STALE=$(git diff --name-only -- 'packages/destination-actions/src/destinations/*/metadata.json' 'packages/browser-destinations/destinations/*/metadata.json' 'packages/warehouse-destinations/src/destinations/*/metadata.json')
Comment on lines +552 to +554
if (filterDirs && filterDirs.size > 0) {
const entryDir: string = entry.directory?.split('/').pop() ?? ''
if (!filterDirs.has(entryDir)) {
Comment on lines +156 to +157
readOnly: field.readOnly ?? null,
hidden: field.unsafe_hidden ?? null,
hasPerformBatch: typeof action.performBatch === 'function',
syncMode,
hooks,
hooks: Object.keys(hooks).length > 0 ? hooks : null,
Browser "plugin" destinations (algolia-plugins, amplitude-plugins, etc.)
share metadata IDs with their cloud counterparts and get merged by
getManifest(), losing their standalone identity. This adds filesystem
scanning to discover them independently and generate their metadata.json.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants