{"_id":"@archallysinc/sf-profile-full","_rev":"2-a2395d1ad849ff5e798ef01552e1a2d6","name":"@archallysinc/sf-profile-full","dist-tags":{"latest":"2.0.0"},"versions":{"1.0.0":{"name":"@archallysinc/sf-profile-full","version":"1.0.0","keywords":["sf-plugin","oclif-plugin"],"author":{"name":"archallysinc"},"license":"MIT","_id":"@archallysinc/sf-profile-full@1.0.0","maintainers":[{"name":"archallys","email":"shibi.ramaiyan@archallysinc.com"}],"homepage":"https://github.com/Archallys-Inc/sf-profile-full#readme","bugs":{"url":"https://github.com/Archallys-Inc/sf-profile-full/issues"},"dist":{"shasum":"d51e971d3c7af9e2319908b2a0de1b9a5fd84bd1","tarball":"https://registry.npmjs.org/@archallysinc/sf-profile-full/-/sf-profile-full-1.0.0.tgz","fileCount":28,"integrity":"sha512-stO3bvtH9AbAzuisQ7ijlIFGUEAagNXufWE+SvzQbBf4Px6K5YHNnEoGSgpIEhUQsiRB6p5Lsy9NWqTlgQGMGg==","signatures":[{"sig":"MEYCIQC6kQ4k/MpmQb8TdJZo0pB3nI7app8yJ5WIwUm+IoswVAIhAMeerpRaXi4TZCsGLZ05l3Ftmfz2uxlZSpTeIUaZThG4","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":47970},"main":"lib/index.js","type":"module","oclif":{"bin":"sf","topics":{"profile":{"description":"Commands to work with Salesforce Profiles."},"profile.retrieve":{"description":"Commands to retrieve Salesforce Profiles."}},"commands":"./lib/commands","topicSeparator":" ","flexibleTaxonomy":true},"types":"lib/index.d.ts","engines":{"node":">=18.0.0"},"gitHead":"635b1b193739a2a8609c437abdd7bed3879d1e2f","scripts":{"lint":"eslint src/ test/ --ext .ts","test":"mocha 'test/**/*.test.ts' --timeout 10000","build":"tsc -p . && node --loader ts-node/esm --no-warnings=ExperimentalWarning node_modules/.bin/oclif manifest","clean":"rm -rf lib oclif.manifest.json","prebuild":"rm -rf lib","build:only":"tsc -p .","test:coverage":"c8 --all --src src --exclude 'src/commands/**' --exclude 'src/index.ts' --100 --reporter text --reporter html mocha 'test/**/*.test.ts' --timeout 10000"},"_npmUser":{"name":"archallys","email":"shibi.ramaiyan@archallysinc.com"},"repository":{"url":"git+https://github.com/Archallys-Inc/sf-profile-full.git","type":"git"},"_npmVersion":"11.6.2","description":"Salesforce CLI plugin to retrieve full Profile metadata via readMetadata()","directories":{},"_nodeVersion":"24.11.1","dependencies":{"@oclif/core":"^4","fast-xml-parser":"^4.5","@salesforce/core":"^8","@salesforce/sf-plugins-core":"^12","@salesforce/source-deploy-retrieve":"^12"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","chai":"^4","mocha":"^10","oclif":"^4","sinon":"^17","eslint":"^8","ts-node":"^10","typescript":"^5","@oclif/test":"^4","@types/chai":"^4","@types/node":"^20","@types/mocha":"^10","@types/sinon":"^17","@salesforce/ts-sinon":"^1","@typescript-eslint/parser":"^7","@typescript-eslint/eslint-plugin":"^7"},"_npmOperationalInternal":{"tmp":"tmp/sf-profile-full_1.0.0_1779984201730_0.9037392402741129","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@archallysinc/sf-profile-full","keywords":["sf-plugin","oclif-plugin"],"description":"Salesforce CLI plugin to retrieve full Profile metadata via readMetadata()","version":"2.0.0","author":{"name":"archallysinc"},"license":"MIT","type":"module","main":"lib/index.js","types":"lib/index.d.ts","homepage":"https://github.com/Archallys-Inc/sf-profile-full#readme","bugs":{"url":"https://github.com/Archallys-Inc/sf-profile-full/issues"},"repository":{"type":"git","url":"git+https://github.com/Archallys-Inc/sf-profile-full.git"},"oclif":{"commands":"./lib/commands","bin":"sf","topicSeparator":" ","topics":{"profile":{"description":"Commands to work with Salesforce Profiles."},"profile.retrieve":{"description":"Commands to retrieve Salesforce Profiles."}},"flexibleTaxonomy":true},"scripts":{"build":"tsc -p . && node --loader ts-node/esm --no-warnings=ExperimentalWarning node_modules/.bin/oclif manifest","prebuild":"rm -rf lib","build:only":"tsc -p .","clean":"rm -rf lib oclif.manifest.json","test":"mocha 'test/**/*.test.ts' --timeout 10000","test:coverage":"c8 --all --src src --exclude 'src/commands/**' --exclude 'src/index.ts' --100 --reporter text --reporter html mocha 'test/**/*.test.ts' --timeout 10000","lint":"eslint src/ test/ --ext .ts"},"dependencies":{"@oclif/core":"^4","@salesforce/core":"^8","@salesforce/sf-plugins-core":"^12","@salesforce/source-deploy-retrieve":"^12","fast-xml-parser":"^4.5"},"devDependencies":{"@oclif/test":"^4","@salesforce/ts-sinon":"^1","@types/chai":"^4","@types/mocha":"^10","@types/node":"^20","@types/sinon":"^17","@typescript-eslint/eslint-plugin":"^7","@typescript-eslint/parser":"^7","c8":"^10.1.3","chai":"^4","eslint":"^8","mocha":"^10","oclif":"^4","sinon":"^17","ts-node":"^10","typescript":"^5"},"engines":{"node":">=18.0.0"},"gitHead":"3b69605683001c23414f0f955d94dde0e7605a01","_id":"@archallysinc/sf-profile-full@2.0.0","_nodeVersion":"24.14.0","_npmVersion":"11.9.0","dist":{"integrity":"sha512-F0mHxCMVi6gzXGPcodhxohw/494C5ZvR++Xl4Z1a4Q6VVGlYVfSz7xkAmjLvtSPnsmF4hrbaoxGI4j+FQRaomQ==","shasum":"ad133b58a71ada068fc553770b985998b975287d","tarball":"https://registry.npmjs.org/@archallysinc/sf-profile-full/-/sf-profile-full-2.0.0.tgz","fileCount":28,"unpackedSize":48017,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDH9M4mFrKAuFANPmVYhFKAvcQVH0ZNQqFqgbryxTKaVwIgQog4uvOOePX6rtyzA+m14GboJm0yac1n4Rq8rCjbPbI="}]},"_npmUser":{"name":"archallys","email":"shibi.ramaiyan@archallysinc.com"},"directories":{},"maintainers":[{"name":"archallys","email":"shibi.ramaiyan@archallysinc.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sf-profile-full_2.0.0_1780083983578_0.45477356577007466"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-28T16:03:21.627Z","modified":"2026-05-29T19:46:23.866Z","1.0.0":"2026-05-28T16:03:21.915Z","2.0.0":"2026-05-29T19:46:23.727Z"},"bugs":{"url":"https://github.com/Archallys-Inc/sf-profile-full/issues"},"author":{"name":"archallysinc"},"license":"MIT","homepage":"https://github.com/Archallys-Inc/sf-profile-full#readme","keywords":["sf-plugin","oclif-plugin"],"repository":{"type":"git","url":"git+https://github.com/Archallys-Inc/sf-profile-full.git"},"description":"Salesforce CLI plugin to retrieve full Profile metadata via readMetadata()","maintainers":[{"name":"archallys","email":"shibi.ramaiyan@archallysinc.com"}],"readme":"# sf-profile-full\n\n> Salesforce CLI plugin that retrieves **complete** Profile metadata using the Metadata API `readMetadata()` call — no more missing Field-Level Security or Layout assignments.\n\n---\n\n## The Problem\n\nThe standard `sf project retrieve` command returns **sparse** profile XML. It only includes sections that correspond to other components already in your local project, which means critical permissions like Field-Level Security (FLS), Layout assignments, Class access, and Page access are often silently dropped.\n\n## The Solution\n\n`sf-profile-full` calls the CRUD-based `readMetadata('Profile', [...])` API directly, which returns the **full** object definition regardless of what exists in your local project or `package.xml` manifest.\n\n---\n\n## Features\n\n- **Complete Profile Retrieval** — Fetches full profile XML including all FLS, layouts, class access, page access, tab visibility, and more.\n- **Flexible Input** — Specify profiles by name (`--name`), auto-detect from a directory (`--sourcedir`), or retrieve all profiles from the org (`--all`).\n- **XML Cleaning** — Optionally strip non-portable elements (login IP ranges, login hours, user license) with `--clean` for safe sandbox ↔ production transfers.\n- **Source Format Output** — Writes `.profile-meta.xml` files compatible with Salesforce DX source format.\n- **Automatic Batching** — Handles the Metadata API's 10-record limit transparently.\n- **Custom Output Directory** — Save profiles anywhere with `--output-dir`.\n\n---\n\n## Prerequisites\n\n- **Node.js** ≥ 18.0.0\n- **Salesforce CLI** (`sf`) installed globally\n- An authenticated Salesforce org\n\n---\n\n## Installation\n\n### Link for Local Development\n\n```bash\ngit clone <repo-url>\ncd sf-profile-full\nnpm install\nnpm run build\nsf plugins link .\n```\n\n### Verify Installation\n\n```bash\nsf profile retrieve full --help\n```\n\n---\n\n## Usage\n\n```\nsf plugins install @archallysinc/sf-profile-full\nsf profile retrieve full [flags]\n```\n\n### Flags\n\n| Flag           | Alias | Required                                               | Description                                                            |\n| -------------- | ----- | ------------------------------------------------------ | ---------------------------------------------------------------------- |\n| `--name`       | `-n`  | One of `--name`, `--sourcedir`, or `--all` is required | Comma-separated profile names to retrieve                              |\n| `--sourcedir`  | `-s`  |                                                        | Directory containing `.profile-meta.xml` files to auto-detect profiles |\n| `--all`        | `-a`  |                                                        | Retrieve **every** profile from the target org                         |\n| `--target-org` |       | **Yes**                                                | Alias or username of the authenticated Salesforce org                  |\n| `--output-dir` | `-d`  | No (default: `force-app/main/default/profiles`)        | Directory where retrieved profiles are saved                           |\n| `--clean`      |       | No (default: `false`)                                  | Strip non-portable elements from the XML                               |\n\n> **Note:** `--name`, `--sourcedir`, and `--all` are mutually exclusive — you must provide exactly one.\n\n### Examples\n\n**Retrieve a single profile:**\n\n```bash\nsf profile retrieve full --name Admin --target-org my-sandbox\n```\n\n**Retrieve multiple profiles by name:**\n\n```bash\nsf profile retrieve full --name Admin,\"Custom Sales Profile\",Standard --target-org my-sandbox\n```\n\n**Auto-detect profiles from a local directory:**\n\n```bash\nsf profile retrieve full --sourcedir force-app/main/default/profiles --target-org my-sandbox\n```\n\n**Retrieve all profiles from the org:**\n\n```bash\nsf profile retrieve full --all --target-org my-sandbox\n```\n\n**Retrieve and clean non-portable elements:**\n\n```bash\nsf profile retrieve full --name Admin --target-org my-sandbox --clean\n```\n\n**Save to a custom directory:**\n\n```bash\nsf profile retrieve full --name Admin --target-org my-sandbox --output-dir src/profiles\n```\n\n---\n\n## What Does `--clean` Remove?\n\nWhen the `--clean` flag is set, the following org-specific elements are stripped from the profile XML:\n\n| Element           | Why Remove?                                                                 |\n| ----------------- | --------------------------------------------------------------------------- |\n| `<loginIpRanges>` | IP restrictions are environment-specific and may block access in other orgs |\n| `<loginHours>`    | Login hour restrictions vary by org policy                                  |\n| `<userLicense>`   | License types may differ between production and sandboxes                   |\n\nThis makes profiles safely portable across sandbox, scratch org, and production environments.\n\n---\n\n## Architecture\n\n```\nsrc/\n├── commands/\n│   └── profile/\n│       └── retrieve/\n│           └── full.ts              # CLI command definition (Oclif)\n├── services/\n│   ├── profileMetadataService.ts    # readMetadata() API call + batching\n│   ├── profileCleaner.ts           # XML cleaning / non-portable element removal\n│   └── formatConverter.ts          # Writes .profile-meta.xml to disk\n├── types/\n│   └── profileTypes.ts             # Shared TypeScript interfaces\n└── index.ts                        # Plugin entry point\n```\n\n### How It Works\n\n```\n┌──────────────────┐     ┌───────────────────────┐     ┌─────────────────┐\n│  CLI Command     │────▶│ ProfileMetadataService │────▶│ Salesforce Org   │\n│  (full.ts)       │     │ (batched readMetadata) │     │ Metadata API     │\n└──────────────────┘     └───────────────────────┘     └─────────────────┘\n        │                           │\n        ▼                           ▼\n┌──────────────────┐     ┌───────────────────────┐\n│ ProfileCleaner   │     │   Raw Profile XML      │\n│ (optional clean) │     │   (complete data)      │\n└──────────────────┘     └───────────────────────┘\n        │\n        ▼\n┌──────────────────┐\n│ FormatConverter   │\n│ (.profile-meta.xml)│\n└──────────────────┘\n```\n\n1. **Command** parses flags and resolves profile names (from `--name`, `--sourcedir`, or `--all`).\n2. **ProfileMetadataService** calls `connection.metadata.read('Profile', batch)` in chunks of 10 (API limit), then builds XML using `fast-xml-parser`.\n3. **ProfileCleaner** (if `--clean` is set) parses the XML tree and removes non-portable nodes.\n4. **FormatConverter** writes the final XML to `<outputDir>/<ProfileName>.profile-meta.xml`.\n\n---\n\n## Development\n\n### Build\n\n```bash\nnpm run build\n```\n\n### Run Tests\n\n```bash\nnpm test\n```\n\n### Lint\n\n```bash\nnpm run lint\n```\n\n### Tech Stack\n\n| Dependency                           | Purpose                                      |\n| ------------------------------------ | -------------------------------------------- |\n| `@oclif/core`                        | CLI framework                                |\n| `@salesforce/sf-plugins-core`        | Salesforce CLI plugin base classes           |\n| `@salesforce/core`                   | Org authentication and Connection management |\n| `@salesforce/source-deploy-retrieve` | Salesforce DX source format utilities        |\n| `fast-xml-parser`                    | XML parsing and building                     |\n| `TypeScript`                         | Type-safe development                        |\n| `Mocha + Chai + Sinon`               | Testing framework                            |\n| `c8`                                 | Code coverage                                |\n\n---\n\n## License\n\n[MIT](LICENSE)\n","readmeFilename":"README.md"}