# Creating Your Own Internal API This guide will walk you through creating and injecting custom Vue APIs for the Dashboard and `@rancher/shell` package by simply dropping a `.api.ts` file in a specific folder. Once set up, you can call your new APIs from any Vue component (e.g. `this.$myNewApi.someMethod()`). --- ## Overview 1. **Naming Convention**: Your primary API classes should end in `.api.ts` (e.g., `my-api.api.ts`). 2. **Location**: Place these files in the `shell/plugins/internal-api/` directory (subdirectories are supported). 3. **Static `apiName()`**: Inside your class, define a static method named `apiName` (e.g., `static apiName() { return 'myNewApi'; }`), which determines the key by which your class is injected into Vue. 4. **Instantiation**: A Vue plugin (`internalApiPlugin`) automatically scans `shell/plugins/internal-api/`, imports each `.api.ts` file, creates a new instance of its default export, and injects it onto the Vue prototype as `$myNewApi`. --- ## Steps to Create & Use a New API 1. **Create a File** Within `shell/plugins/internal-api/` (or its subdirectories), create a `.api.ts` file. For example: `shell/plugins/internal-api/my-api.api.ts` 2. **Export a Default Class** Your class should extend the provided `BaseApi` class. This ensures that your API has access to common functionality (like the Vuex store) without reimplementing it for every API. The class must have: - A constructor that calls the `BaseApi` constructor with the Vuex.Store instance. - A static `apiName` method defining how it will be injected. - Custom methods or logic you need to expose to components. Example: ```ts // shell/plugins/internal-api/my-api.api.ts import { BaseApi } from "@shell/plugins/internal-api/shared/base-api"; export default class MyApi extends BaseApi { // Name under which this API is injected => this.$myApi // The `$` prefix will be automatically added when the API is injected static apiName() { return "myApi"; } public doSomething() { console.log("Hello from MyApi"); } } ``` 3. **Usage in Vue Components** Once the file is saved, the `internalApiPlugin` (as shown in your `install-plugins.js`) will automatically discover your API file (e.g. `my-api.api.ts`), instantiate it with the Vuex store, and inject an instance of `MyApi` onto the Vue prototype. This means that: - In an Options API component, you can access your API via this.$myApi. - In a Composition API component, you can access it using getCurrentInstance() (or via other injection methods) to retrieve the global properties. ### Options API Example ```vue ``` ### Composition API Example ```vue ``` --- ## TypeScript Augmentation (Optional) To get TypeScript IntelliSense for `this.$myApi`, you can manually augment the `vue` module. You can create a declaration file (e.g., `my-api.d.ts`) in the API Folder: ```ts import type MyApi from "@shell/plugins/internal-api/my-api.api"; export {}; declare module "vue" { interface ComponentCustomProperties { $myApi: MyApi; } } ``` Now, TypeScript will recognize `this.$myApi` in your Vue components. --- ## File Structure Example Below is an example file structure showing multiple APIs in subdirectories: ``` shell/plugins/internal-api/ ├── my-api.api.ts ├── cluster/ │ ├── cluster-tools.api.ts │ └── some-helper.ts <-- not injected └── rancher/ └── rancher.api.ts ``` Each `.api.ts` file is automatically discovered and instantiated. Helpers or partial modules that do not follow the `.api.ts` naming scheme (like `some-helper.ts`) won’t be injected. --- ## How It Works - **`install-plugins.js`** includes `internalApiPlugin` in `installInjectedPlugins()`. - **`internalApiPlugin`** uses `require.context` to scan subdirectories under `shell/plugins/internal-api/`. - For each file matching `*.api.ts`, it: 1. Imports the file. 2. Reads the default export (your class). 3. Checks for a static `apiName` method; if not found, it falls back to the file name (An error will be thrown if extending the `BaseApi` class). 4. Instantiates the class, passing in the Vuex store. 5. Calls `inject(key, instance)`, which attaches your API to `Vue.prototype.$key`. --- ## Conclusion With this setup: 1. **Create** a `.api.ts` class in `shell/plugins/internal-api/`. 2. **Define** `static apiName() { return 'something'; }`. 3. **Use** it in Vue components via `this.$something`. Everything else—from discovery to injection—happens automatically. This approach keeps your code organized, fosters easy extension, and saves you from having to manually edit the main injection logic each time you add a new API.