|
1 | 1 | # Copilot Instructions for CLI for Microsoft 365 |
2 | 2 |
|
3 | 3 | ## Project Overview |
| 4 | + |
4 | 5 | - This is a cross-platform CLI tool to manage Microsoft 365 tenants and SharePoint Framework (SPFx) projects. |
5 | 6 | - Written in TypeScript, targeting Node.js LTS (see `package.json`, `tsconfig.json`). |
6 | 7 | - Main entry: `src/index.ts` → `src/cli/cli.ts` (command parsing/execution). |
|
10 | 11 | - Command discovery/build: see `scripts/write-all-commands.js` (generates `allCommands.json`). |
11 | 12 |
|
12 | 13 | ## Key Patterns & Conventions |
| 14 | + |
13 | 15 | - **Global options**: All commands accept `--output`, `--query`, `--debug`, `--verbose` (see `src/GlobalOptions.ts`). |
14 | 16 | - **Authentication**: Managed via `src/Auth.ts`, supports multiple auth types (Device Code, Certificate, Secret, Managed Identity, etc.). |
15 | 17 | - **HTTP requests**: Use the wrapper in `src/request.ts` (Axios-based, with logging/debug hooks). |
|
19 | 21 | - **Config**: User settings/configuration via `configstore` (see `src/config.ts`). |
20 | 22 | - **Completion**: Shell completion logic/scripts in `scripts/Register-CLIM365Completion.ps1` and `scripts/Test-CLIM365Completion.ps1`. |
21 | 23 |
|
| 24 | +## Command Implementation |
| 25 | + |
| 26 | +- Command class should extend the appropriate workload-specific base class (`SpoCommand`, `GraphCommand`, `AzmgmtCommand`, etc.) when applicable; otherwise, it may extend `Command` directly. |
| 27 | +- Class name must follow the `[Service][Entity][Action]Command` pattern (e.g., `SpoGroupGetCommand`). |
| 28 | +- Must implement `name`, `description`, and `commandAction()` at minimum. |
| 29 | +- Options must be defined using **Zod schemas** with `z.strictObject({ ...globalOptionsZod.shape, ... })` or `globalOptionsZod.strict()`. |
| 30 | +- Option names must be camelCase; apply aliases with the schema `.alias('x')` method (for example, `.alias('u')` for `--webUrl` where appropriate). |
| 31 | +- Commands that delete/remove resources must include a `--force` option. |
| 32 | +- Use `async/await`, never `.then()` chains. |
| 33 | +- Use `logger.logToStderr()` for verbose/debug messages, never `logger.log()`. |
| 34 | +- Add verbose log messages where they provide useful execution context; every command requires at least one verbose logging statement. |
| 35 | +- Never format output conditionally based on `--output json`; use `defaultProperties` for text field filtering. |
| 36 | +- All `commands.ts` files are sorted alphabetically by command name; new commands must be added in the correct order. |
| 37 | + |
| 38 | +## API Usage |
| 39 | + |
| 40 | +- Use `request.ts` wrapper for all HTTP calls, never call APIs directly. |
| 41 | +- Use `handleRejectedODataJsonPromise()` for JSON response error handling. |
| 42 | +- For SharePoint: use `GetFileByServerRelativePath` / `GetFolderByServerRelativePath`, never `GetFileByServerRelativeUrl` / `GetFolderByServerRelativeUrl`. |
| 43 | +- Escape user input in XML payloads and URL parameters using `formatting.encodeQueryParameter()` or `formatting.escapeXml()`. |
| 44 | +- Avoid unnecessary form digest retrieval. |
| 45 | + |
| 46 | +## Testing |
| 47 | + |
| 48 | +- Test file must be alongside the command file with `.spec.ts` extension. |
| 49 | +- Use Mocha (`describe`/`it`/`before`/`beforeEach`/`afterEach`/`after`) + Sinon (stubs/spies). |
| 50 | +- Standard test setup must stub: `auth.restoreAuth`, `telemetry.trackEvent`, `pid.getProcessName`, `session.getId`. |
| 51 | +- Must set `auth.connection.active = true` in `before()`. |
| 52 | +- Must initialize `commandInfo` and `commandOptionsSchema` in `before()` for Zod-based commands. |
| 53 | +- Must include tests for: command name matches constant, description is not null, schema validation (valid and invalid options), success paths, error handling paths. |
| 54 | +- Options in `command.action()` calls must be parsed through `commandOptionsSchema.parse()`, not passed as raw objects. |
| 55 | +- Never use `as any` to bypass type checking unless absolutely necessary for error path testing. |
| 56 | +- Use `sinon.restore()` in `after()` to reset stubs/spies. |
| 57 | + |
| 58 | +## Documentation |
| 59 | + |
| 60 | +- Every command needs a reference page at `docs/docs/cmd/<workload>/<command-name>.mdx`. |
| 61 | +- The `.mdx` file name matches the command file name. |
| 62 | +- Must include: title, description, usage, options table, examples, permissions, and response. |
| 63 | +- The remarks section can be used for additional information but is not mandatory. |
| 64 | +- When a command has a response, include sample output for all four output formats: JSON, Markdown, text, and CSV. |
| 65 | +- Include at least 2 examples for the examples section, covering different option combinations. |
| 66 | +- Import and use `<Global />` for standard CLI options. |
| 67 | +- Examples should use `m365` prefix and long option names (not short aliases). |
| 68 | +- Document minimum required permissions that allow success with any option combination. |
| 69 | +- Docs must build without warnings. |
| 70 | +- When importing components in the docs, use absolute imports from `@site/src/components/` instead of relative paths. |
| 71 | +- When importing global options in the docs, use a relative import from `../_global.mdx`. |
| 72 | + |
| 73 | +## Code Quality |
| 74 | + |
| 75 | +- No `any` types — use proper TypeScript interfaces/types. |
| 76 | +- No commented-out code. |
| 77 | +- Single quotes for all strings, where possible. |
| 78 | +- No unused imports or variables. |
| 79 | +- Follow existing patterns in neighboring command files for consistency. |
| 80 | +- Custom ESLint rules are enforced: command class naming, command name dictionary, no deprecated API usage. |
| 81 | +- New command name words may require adding to the ESLint dictionary in `eslint.config.mjs`. |
| 82 | + |
22 | 83 | ## Developer Workflows |
| 84 | + |
23 | 85 | - **Build**: `npm run build` (TypeScript compile + command metadata generation) |
24 | 86 | - **Test**: `npm test` (runs version check, lint, and Mocha tests) |
25 | 87 | - **Lint**: `npm run lint` (uses custom ESLint rules from `eslint-rules/`) |
|
29 | 91 | - **Docs**: Docusaurus site in `docs/` (config: `docs/docusaurus.config.ts`) |
30 | 92 |
|
31 | 93 | ## Project-Specific Notes |
32 | | -- **Command structure**: Each command is a class, not a function. Use inheritance from `Command`. |
| 94 | + |
33 | 95 | - **Command registration**: New commands must be discoverable for `write-all-commands.js` to pick up. |
34 | 96 | - **SPFx support**: Special logic for SPFx project upgrades and compatibility checks in `src/m365/spfx/`. |
35 | 97 | - **Output**: Prefer returning objects/arrays; formatting handled by CLI core. |
36 | | -- **No direct file/console output in commands**: Use provided logger and output mechanisms. |
37 | | -- **Testing**: Mocha-based, see test files alongside source (e.g., `*.spec.ts`). 100% code coverage. |
38 | | -- **Custom ESLint rules**: See `eslint-rules/` and `eslint-plugin-cli-microsoft365` in `package.json`. |
39 | 98 |
|
40 | 99 | ## Integration & External Dependencies |
| 100 | + |
41 | 101 | - **Microsoft Graph, SharePoint REST, etc.**: Use `request.ts` for all HTTP calls. |
42 | 102 | - **Authentication**: Uses `@azure/msal-node` and related packages. |
43 | 103 | - **Telemetry**: Application Insights via `applicationinsights` package. |
44 | 104 | - **Docs**: Docusaurus, see `docs/` and `docs/docusaurus.config.ts`. |
45 | 105 |
|
46 | 106 | ## Examples |
| 107 | + |
47 | 108 | - Add a new command: Get the latest information about building commands from [the docs](../docs/docs/contribute/new-command/build-command-logic.mdx). Create a class in the appropriate `src/m365/<workload>/commands/` folder, extend `Command`, implement `commandAction`, register options, and ensure it is discoverable. Create a test file next to the command file. Create a reference page in the documentation in `docs/docs/cmd/<workload>`. The reference page file name is the same as the command file name, but with the `.mdx` extension. |
48 | 109 | - Add a global option: update `src/GlobalOptions.ts` and propagate to command parsing in `src/cli/cli.ts`. |
49 | 110 |
|
50 | 111 | ## References |
| 112 | + |
51 | 113 | - [Main README](../README.md) |
52 | 114 | - [Contributing Guide](../docs/docs/contribute/contributing-guide.mdx) |
53 | 115 | - [Docs site](https://pnp.github.io/cli-microsoft365/) |
0 commit comments