Skip to content

Commit

Permalink
- Fixed output directory issue.
Browse files Browse the repository at this point in the history
- Added init command.
- Added add command.
- Added refresh command.
- Updated config command.
  • Loading branch information
rahulgawale committed Jun 14, 2024
1 parent 8a0610a commit 1d7672e
Show file tree
Hide file tree
Showing 14 changed files with 348 additions and 104 deletions.
20 changes: 20 additions & 0 deletions .changeset/nice-nails-give.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
"@forcetrails/sobject-types": major
---

# v0.2.0
- Fixed output directory issue.
- Added init command.
- Added add command.
- Added refresh command.
- Updated config command.
- Updated list command.
- Changed config file name to `.ftypesc.json`
- Changed default configuration
- Changed output directory to `.ftypes`
- Added `sfdxDir` with default value `../.sfdx/sfdx-config.json` - looks for sfdx config in cwd
- Removed `config.json`.
- Updated `tsconfig.json`.
- Added initialization checks - `checkInitialization()`.
- Update readme.md with docs.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ dist
node_modules
package-lock.json
app.log
.ftypes
96 changes: 94 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,94 @@
# Adding Type Checking and SObject Intellisense for to Lightning Web Components
-- more stuff coming up
# @forcetrails/sobject-types

## Overview

The `@forcetrails/sobject-types` Tool is a command-line utility built to automate the generation of TypeScript definition files (.d.ts) for Salesforce objects. These definition files are crucial for projects containing TypeScript LWC components or LWC components with JSDocs, providing type safety and autocompletion support.

The tool fetches metadata for specified Salesforce objects, extracts fields and their corresponding data types, and generates TypeScript interfaces that mirror the structure of these Salesforce objects.

## Prerequisites

Before installing and using the tool, ensure you have the following prerequisites:

- Node.js (version >= 12.0.0)
- npm (Node Package Manager)
- Salesforce CLI installed and authenticated with at least one Salesforce organization. Install Salesforce CLI from here.

## Installation

#### 1. Install using npm

```bash
npm i @forcetrails/sobject-types
```

#### 2. Configure Salesforce Connection:

Update the `./ftypes/ftypesc.json` file with your Salesforce credentials and desired configuration (e.g., Salesforce objects to generate .d.ts files for, output directory).

#### 3. Run the command
```bash
npx ftypes
```

## Usage

### Commands

- `ftypes init` Initialize the ftypes configuration
- `ftypes list` List all sObjects from config file
- `ftypes config` Show config contents
- `ftypes set-target-org <orgname>` Set the default Salesforce organization username in `./ftypes/ftypesc.json`. **This is alias of already authenticated Salesforce org from sf auth
- `ftypes add <objname>` Add type definitions for a specific object
- `ftypes refresh <objname...>` Add type definitions for a specific object(s)
- `ftypes` Generate Typings for all SObjects from config

### Examples
#### 1. Init `ftypes` project with default configuration:

```bash
ftypes init
```
This command creates `.ftypes` file in the current work directory and adds default configuration for types generation

#### 2. Generate `.d.ts` file for all objects mentioned config:
```bash
ftypes
```

#### 3. Add Object a specific to configuration and generate types:

```bash
ftypes add Account
```
This command adds `Account` object to config list and generates Types for account object

#### 4. Refresh typings of existing Object:

```bash
ftypes refresh Account
```
This command regenerates `Account.d.ts` in the specified output directory.

### 5. List all configured Salesforce objects:

```bash
ftypes list
```
Lists all Salesforce objects configured in config file(`./ftypes/ftypesc.json`).

#### 6. Set default Salesforce organization username:

```bash
ftypes set-target-org my-sf-org
```
Sets defaultusername in `./ftypes/ftypesc.json` to `my-sf-org` in your sfdx project.

#### 7. Display contents of (`./ftypes/ftypesc.json`):

```bash
ftypes configs
```
Displays the contents of the configuration file (`./ftypes/ftypesc.json`).

More features coming soon...
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@forcetrails/sobject-types",
"version": "0.1.0",
"version": "0.2.0",
"description": "SObject and Field Types for Lightning Web Components TypeScript or JSDOC, to enable Type Safety and Intellisense",
"repository": {
"type": "git",
Expand Down
54 changes: 54 additions & 0 deletions src/commands/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import path from 'path';
import fs from 'fs/promises';
import logger from '../logger';
import { configFileName, rootDir } from '../config';
import { config } from '../data/ftypesc';
import { scriptName } from '../types';

export async function initCommand() {
try {
const configDir = path.resolve(process.cwd(), './' + rootDir);
const configFilePath = path.join(configDir, configFileName);

// Ensure the directory exists
await fs.mkdir(configDir, { recursive: true });

// Write the default configuration file
const defaultConfig = config;

await fs.writeFile(configFilePath, JSON.stringify(defaultConfig, null, 2));
await addToGitignoreIfNotPresent();
logger.info(`Configuration initialized at ${configFilePath}, now run below command to generate types.\n\n--->\t${scriptName}\n`);
} catch (error) {
logger.error('Error initializing configuration:', error);
}
}

export async function addToGitignoreIfNotPresent() {
try {
// Check if .gitignore file exists in the current directory
const gitignorePath = path.resolve(process.cwd(), '.gitignore');
const gitignoreExists = await fs.access(gitignorePath).then(() => true).catch(() => false);

if (gitignoreExists) {
// Read the contents of .gitignore
let gitignoreContent = await fs.readFile(gitignorePath, 'utf8');

// Check if rootDir is already listed in .gitignore
if (!gitignoreContent.includes(rootDir)) {
// Append rootDir to .gitignore
gitignoreContent += `\n${rootDir}\n`;

// Write back the updated content to .gitignore
await fs.writeFile(gitignorePath, gitignoreContent, 'utf8');
logger.info(`${rootDir} added to .gitignore`);
} else {
logger.info(`${rootDir} already exists in .gitignore`);
}
} else {
logger.info('.gitignore file not found in the current directory');
}
} catch (error) {
logger.error('Error modifying .gitignore:' + JSON.stringify(error));
}
}
17 changes: 0 additions & 17 deletions src/config.json

This file was deleted.

81 changes: 55 additions & 26 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,70 @@ import * as fs from 'fs/promises';
import * as path from 'path';
import { Config, SfdxConfig } from './types';
import { saveToFile } from './utils';
import logger from './logger';

export const configFileName = 'ftypesc.json';
export const rootDir = '.ftypes'

// Define the path to the configuration file
const configFilePath = path.resolve(__dirname, 'config.json');
const sfdxConfigPath = path.resolve(__dirname, '.sfdx', 'sfdx-config.json');

let config: Config;
async function readConfigFile(filePath: string): Promise<Config> {
const data = await fs.readFile(filePath, 'utf8');
config = JSON.parse(data) as Config;
return config;
export function getConfigPath() {
return path.join(process.cwd(), rootDir, configFileName);
}

export async function checkInitialization() {
try {
await getConfig();
} catch (error) {
logger.error(`ftypes is not initialized. Please run "ftypes init" to set up the configuration.`);
// Exit the process if not initialized
process.exit(1);
}
}

export async function getConfig() {
if (!config)
return await readConfigFile(configFilePath);
return config;
};
const getConfig = (() => {
let config: Config | null = null;

return async (): Promise<Config> => {
if (config) {
return config;
}
try {
const configData = await fs.readFile(getConfigPath(), 'utf-8');
config = JSON.parse(configData) as Config;
return config;
} catch (error) {
logger.error(`Error reading configuration file at ${getConfigPath()}:`, error);
throw new Error('Failed to read configuration file');
}
};
})();

// update config
export async function saveConfig(config: Config) {
await saveToFile(configFilePath, JSON.stringify(config));
await saveToFile(getConfigPath(), JSON.stringify(config));
await getConfig();
}

// sfdx config
let sfdxConfig: SfdxConfig;
const getSfdxConfig = (() => {
let sfdxConfig: SfdxConfig | null = null;

async function readSfdxConfigFile(filePath: string): Promise<SfdxConfig> {
const data = await fs.readFile(filePath, 'utf8');
sfdxConfig = JSON.parse(data) as SfdxConfig;
return sfdxConfig;
}
return async (): Promise<SfdxConfig> => {
if (sfdxConfig) {
return sfdxConfig;
}

try {
const config = await getConfig();
const sfdxcPath = path.resolve(process.cwd(), config.sfdxDir);
const data = await fs.readFile(sfdxcPath, 'utf8');
return JSON.parse(data) as SfdxConfig;
} catch (error) {
logger.error(`Error reading SFDX configuration file:`, error);
throw new Error('Failed to read SFDX configuration file');
}
};
})();

export async function getSfdxConfig() {
if (!sfdxConfig)
return await readSfdxConfigFile(sfdxConfigPath);
return sfdxConfig;
};
export { getConfig, getSfdxConfig }


18 changes: 18 additions & 0 deletions src/data/ftypesc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export const config = {
sObjects: [
"Account",
"Contact",
"Lead",
"Case",
"Opportunity",
"OpportunityLineItem",
"Order",
"OrderItem",
"Quote",
"QuoteLineItem"]
,
sfPath: "sf",
outputDir: "./.ftypes/typings",
defaultusername: "gunguna-dev",
sfdxDir: "../.sfdx/sfdx-config.json"
};
2 changes: 1 addition & 1 deletion src/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ function getPicklistTypes(objName: string, field: SObjectFieldSchema[]) {

field.filter(f => f.type === "picklist").forEach(f => {
let tName = `${objName}_${f.name}_Picklist`;
picklistTypes.typeDefs.push(`type ${tName} = ${buildPicklist(f)};`)
picklistTypes.typeDefs.push(`type ${tName} = ${buildPicklist(f)}${f.restrictedPicklist === true ? '' : ' | string'};`)
picklistTypes.typeNames.set(f.name, tName);
})

Expand Down
Loading

0 comments on commit 1d7672e

Please sign in to comment.