Init
This commit is contained in:
commit
0029086b3f
148 changed files with 19047 additions and 0 deletions
287
commands/add-object/add-object.js
Executable file
287
commands/add-object/add-object.js
Executable file
|
@ -0,0 +1,287 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
// Template Fields
|
||||
// - nameFirst
|
||||
// - nameCamel
|
||||
// - nameSnakeUpper
|
||||
// - nameUpper
|
||||
// - nameLower
|
||||
// - nameKebab
|
||||
// - apiCreateFields "field1, field2, field3"
|
||||
// - apiUpdateFields "blankId, field1, field2, field3"
|
||||
// - primaryKey "blankId"
|
||||
// - seedData {"blankId": "", "field1": ""},{"blankId": "", "field1": ""}
|
||||
// - mapperFields blankId: data?.blankId, field1: data?.field1
|
||||
// - typeFields blankId: string; field1: string;
|
||||
|
||||
const fs = require('fs');
|
||||
const readlineSync = require('readline-sync');
|
||||
const YAML = require('js-yaml');
|
||||
|
||||
const functionNames = [
|
||||
'And',
|
||||
'Base64',
|
||||
'Cidr',
|
||||
'Condition',
|
||||
'Equals',
|
||||
'FindInMap',
|
||||
'GetAtt',
|
||||
'GetAZs',
|
||||
'If',
|
||||
'ImportValue',
|
||||
'Join',
|
||||
'Not',
|
||||
'Or',
|
||||
'Ref',
|
||||
'Select',
|
||||
'Split',
|
||||
'Sub',
|
||||
];
|
||||
|
||||
class CustomTag {
|
||||
constructor(type, data) {
|
||||
this.type = type;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
function yamlType(name, kind) {
|
||||
const functionName = ['Ref', 'Condition'].includes(name) ? name : `!${name}`;
|
||||
return new YAML.Type(`${functionName}`, {
|
||||
kind,
|
||||
multi: true,
|
||||
representName: function (object) {
|
||||
return object.type;
|
||||
},
|
||||
represent: function (object) {
|
||||
return object.data;
|
||||
},
|
||||
instanceOf: CustomTag,
|
||||
construct: function (data, type) {
|
||||
return new CustomTag(type, data);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function generateTypes() {
|
||||
const types = functionNames
|
||||
.map((functionName) =>
|
||||
['mapping', 'scalar', 'sequence'].map((kind) =>
|
||||
yamlType(functionName, kind),
|
||||
),
|
||||
)
|
||||
.flat();
|
||||
return types;
|
||||
}
|
||||
|
||||
const writeServerlessApiYaml = () => {
|
||||
const yamlTypes = generateTypes();
|
||||
const schema = YAML.DEFAULT_SCHEMA.extend(yamlTypes);
|
||||
|
||||
const serverlessFile = fs.readFileSync(
|
||||
`${projectRoot}/packages/api/serverless.yml`,
|
||||
'utf8',
|
||||
);
|
||||
const yamlJson = YAML.load(serverlessFile, { schema: schema });
|
||||
const filenameName = `${toKebabCase(name.toLowerCase())}`;
|
||||
|
||||
const newFunction = `\${file(./src/baseblocks/${filenameName}/${filenameName}-functions.yml)}`;
|
||||
const newResource = `\${file(./src/baseblocks/${filenameName}/${filenameName}-dynamodb.yml)}`;
|
||||
if (
|
||||
yamlJson.functions.find((i) => i === newFunction) ||
|
||||
yamlJson.resources.find((i) => i === newResource)
|
||||
) {
|
||||
console.log('Conflicting resource/function in serverless.yml, not saving.');
|
||||
return;
|
||||
}
|
||||
|
||||
yamlJson.functions.push(newFunction);
|
||||
yamlJson.resources.push(newResource);
|
||||
yamlJson.provider.iam.role.statements[0].Resource.push(
|
||||
new CustomTag('!Sub', `\${${toCamelCase(name)}Table.Arn}`),
|
||||
new CustomTag('!Sub', `\${${toCamelCase(name)}Table.Arn}/index/*`),
|
||||
);
|
||||
yamlJson.custom['serverless-dynamodb'].seed.local.sources.push({
|
||||
table: `\${env:APP_NAME}-\${opt:stage}-${filenameName}`,
|
||||
sources: [`./src/baseblocks/${filenameName}/${filenameName}.seed.json`],
|
||||
});
|
||||
|
||||
const yamlResult = YAML.dump(yamlJson, {
|
||||
schema,
|
||||
});
|
||||
|
||||
fs.writeFileSync(`${projectRoot}/packages/api/serverless.yml`, yamlResult);
|
||||
};
|
||||
|
||||
const toCamelCase = (str) => {
|
||||
return str
|
||||
.replace(/(?:^\w|[A-Z]|\b\w)/g, function (word, index) {
|
||||
return index === 0 ? word.toLowerCase() : word.toUpperCase();
|
||||
})
|
||||
.replace(/\s+/g, '');
|
||||
};
|
||||
|
||||
const toKebabCase = (str) =>
|
||||
str &&
|
||||
str
|
||||
.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
|
||||
.map((x) => x.toLowerCase())
|
||||
.join('-');
|
||||
|
||||
const cwd = process.cwd();
|
||||
// console.log(`Current Working Dir: ${cwd}`);
|
||||
const projectRoot = cwd.split('/commands')[0];
|
||||
// console.log(`Project Root: ${projectRoot}`);
|
||||
const templatePath = `${cwd}/template`;
|
||||
// console.log(`Template Path: ${templatePath}`);
|
||||
|
||||
let name = readlineSync.question('What is the name of the new object? ');
|
||||
|
||||
console.log(`Creating new object [${name}]`);
|
||||
|
||||
// Support multi words in kebab case, pascal case or snake case
|
||||
if (name.includes('-')) {
|
||||
name = name.split('-').join(' ');
|
||||
} else if (name.includes('_')) {
|
||||
name = name.split('_').join(' ');
|
||||
} else {
|
||||
name = name
|
||||
.replace(/([A-Z][a-z])/g, ' $1')
|
||||
.replace(/(\d)/g, ' $1')
|
||||
.trim();
|
||||
}
|
||||
|
||||
const primaryKey = `${toCamelCase(name)}Id`;
|
||||
const inputFields = [];
|
||||
var fieldName = '';
|
||||
do {
|
||||
console.log('Current Fields:', [
|
||||
primaryKey,
|
||||
...inputFields.map((i) => i.name),
|
||||
]);
|
||||
fieldName = readlineSync.question('New field name (or enter to finish): ');
|
||||
if (fieldName) {
|
||||
const tsTypes = ['string', 'number', 'boolean', 'any', 'string[]'];
|
||||
const index = readlineSync.keyInSelect(tsTypes, 'Type?');
|
||||
const tsType = tsTypes[index];
|
||||
const isRequired = readlineSync.keyInYN('is field required?');
|
||||
console.log(
|
||||
`Added field [${fieldName}${isRequired ? '' : '?'}: ${tsType}]\n`,
|
||||
);
|
||||
inputFields.push({
|
||||
name: fieldName,
|
||||
tsType: tsType,
|
||||
isRequired: isRequired,
|
||||
});
|
||||
}
|
||||
} while (fieldName);
|
||||
|
||||
const fields = inputFields.map((field) => field.name);
|
||||
const allFields = [primaryKey, ...fields];
|
||||
|
||||
let dataTypeFields = ` ${primaryKey}: string;`;
|
||||
inputFields.forEach((field) => {
|
||||
dataTypeFields = `${dataTypeFields}\n ${field.name}${
|
||||
field.isRequired ? '' : '?'
|
||||
}: ${field.tsType};`;
|
||||
});
|
||||
|
||||
let dataMapperFields = '';
|
||||
allFields.forEach((field) => {
|
||||
dataMapperFields = `${dataMapperFields}\n ${field}: data?.${field},`;
|
||||
});
|
||||
|
||||
const data = {
|
||||
name,
|
||||
nameFirst: `${name[0].toUpperCase()}${toCamelCase(name.slice(1))}`,
|
||||
nameCamel: `${toCamelCase(name)}`,
|
||||
nameSnakeUpper: `${name.replace(/\s/g, '_').toUpperCase()}`,
|
||||
nameUpper: `${name.toUpperCase()}`,
|
||||
nameLower: `${name.toLowerCase()}`,
|
||||
nameKebab: `${toKebabCase(name.toLowerCase())}`,
|
||||
apiCreateFields: fields.join(', '),
|
||||
apiUpdateFields: allFields.join(', '),
|
||||
primaryKey: `${toCamelCase(name)}Id`,
|
||||
seedData: ``,
|
||||
mapperFields: dataMapperFields,
|
||||
typeFields: dataTypeFields,
|
||||
};
|
||||
|
||||
const renderTemplate = (template) => {
|
||||
let generatedContent = template;
|
||||
Object.keys(data).forEach((key) => {
|
||||
generatedContent = generatedContent.replace(
|
||||
new RegExp(`{{ ${key} }}`, 'g'),
|
||||
data[key],
|
||||
);
|
||||
});
|
||||
return generatedContent;
|
||||
};
|
||||
|
||||
const apiOutputPath = `${projectRoot}/packages/api/src/baseblocks/${toKebabCase(
|
||||
name.toLowerCase(),
|
||||
)}`;
|
||||
const filenameName = `${toKebabCase(name.toLowerCase())}`;
|
||||
const files = [
|
||||
{
|
||||
templateFile: `${templatePath}/api/blank.ts`,
|
||||
outputPath: apiOutputPath,
|
||||
outputFilename: `${apiOutputPath}/${filenameName}.ts`,
|
||||
},
|
||||
{
|
||||
templateFile: `${templatePath}/api/blank.service.ts`,
|
||||
outputPath: apiOutputPath,
|
||||
outputFilename: `${apiOutputPath}/${filenameName}.service.ts`,
|
||||
},
|
||||
{
|
||||
templateFile: `${templatePath}/api/blank.seed.json`,
|
||||
outputPath: apiOutputPath,
|
||||
outputFilename: `${apiOutputPath}/${filenameName}.seed.json`,
|
||||
},
|
||||
{
|
||||
templateFile: `${templatePath}/api/blank-functions.yml`,
|
||||
outputPath: apiOutputPath,
|
||||
outputFilename: `${apiOutputPath}/${filenameName}-functions.yml`,
|
||||
},
|
||||
{
|
||||
templateFile: `${templatePath}/api/blank-dynamodb.yml`,
|
||||
outputPath: apiOutputPath,
|
||||
outputFilename: `${apiOutputPath}/${filenameName}-dynamodb.yml`,
|
||||
},
|
||||
{
|
||||
templateFile: `${templatePath}/api/blank-api.ts`,
|
||||
outputPath: apiOutputPath,
|
||||
outputFilename: `${apiOutputPath}/${filenameName}-api.ts`,
|
||||
},
|
||||
{
|
||||
templateFile: `${templatePath}/types/blank.d.ts`,
|
||||
outputPath: `${projectRoot}/shared/types`,
|
||||
outputFilename: `${projectRoot}/shared/types/${filenameName}.d.ts`,
|
||||
},
|
||||
{
|
||||
templateFile: `${templatePath}/client-api/blank.ts`,
|
||||
outputPath: `${projectRoot}/shared/client-api`,
|
||||
outputFilename: `${projectRoot}/shared/client-api/${filenameName}.ts`,
|
||||
},
|
||||
];
|
||||
|
||||
const fileOperations = async (file) => {
|
||||
const templateFileData = fs.readFileSync(file.templateFile).toString();
|
||||
const result = renderTemplate(templateFileData);
|
||||
await fs.promises.mkdir(file.outputPath, {
|
||||
recursive: true,
|
||||
});
|
||||
console.log(`Creating ${file.outputFilename}`);
|
||||
fs.writeFileSync(file.outputFilename, result);
|
||||
};
|
||||
|
||||
(async () => {
|
||||
console.log('Creating files...');
|
||||
for (let filePos = 0; filePos < files.length; filePos++) {
|
||||
const file = files[filePos];
|
||||
await fileOperations(file);
|
||||
}
|
||||
console.log('Updating api serverless.yml');
|
||||
writeServerlessApiYaml();
|
||||
console.log('Done!');
|
||||
})();
|
14
commands/add-object/package.json
Normal file
14
commands/add-object/package.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "@baseline/add-object",
|
||||
"version": "1.0.0",
|
||||
"main": "add-object.js",
|
||||
"scripts": {
|
||||
"start": "./add-object.js",
|
||||
"lint": "echo 'No linting'",
|
||||
"pretty": "npx prettier --write '*.{ts,tsx,js,json,css,scss,md,yml,yaml,html}'"
|
||||
},
|
||||
"devDependencies": {
|
||||
"readline-sync": "1.4.10",
|
||||
"js-yaml": "4.1.0"
|
||||
}
|
||||
}
|
102
commands/add-object/template/api/blank-api.ts
Normal file
102
commands/add-object/template/api/blank-api.ts
Normal file
|
@ -0,0 +1,102 @@
|
|||
import { Response } from 'express';
|
||||
import { {{ nameCamel }}Mapper } from './{{ nameKebab }}';
|
||||
import { isAdmin } from '../../middleware/is-admin';
|
||||
import { RequestContext } from '../../util/request-context.type';
|
||||
import { {{ nameFirst }} } from '@baseline/types/{{ nameKebab }}';
|
||||
import { getErrorMessage } from '../../util/error-message';
|
||||
import createApp from '../../util/express-app';
|
||||
import createAuthenticatedHandler from '../../util/create-authenticated-handler';
|
||||
import { {{ nameCamel }}Service } from './{{ nameKebab }}.service';
|
||||
|
||||
const app = createApp();
|
||||
// app.use(isAdmin); // All private endpoints require the user to be an admin
|
||||
export const handler = createAuthenticatedHandler(app);
|
||||
|
||||
app.post('/{{ nameKebab }}', [
|
||||
isAdmin,
|
||||
async (req: RequestContext, res: Response) => {
|
||||
try {
|
||||
const { {{ apiCreateFields }} } = req.body as {{ nameFirst }};
|
||||
const {{ nameCamel }}Data: Partial<{{ nameFirst }}> = {
|
||||
{{ apiCreateFields }},
|
||||
};
|
||||
const {{ nameCamel }} = await {{ nameCamel }}Service.create({{ nameCamel }}Data);
|
||||
res.json({{ nameCamel }}Mapper({{ nameCamel }}));
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
console.error(`Failed to create {{ nameLower }} ${message}`);
|
||||
res.status(400).json({ error: 'Failed to create {{ nameLower }}' });
|
||||
}
|
||||
},
|
||||
]);
|
||||
|
||||
app.patch('/{{ nameKebab }}', [
|
||||
isAdmin,
|
||||
async (req: RequestContext, res: Response) => {
|
||||
try {
|
||||
const { {{ apiUpdateFields }} } = req.body as {{ nameFirst }};
|
||||
const {{ nameCamel }}Data: Partial<{{ nameFirst }}> = {
|
||||
{{ apiUpdateFields }}
|
||||
};
|
||||
const {{ nameCamel }} = await {{ nameCamel }}Service.update({{ nameCamel }}Data);
|
||||
res.json({{ nameCamel }}Mapper({{ nameCamel }}));
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
console.error(`Failed to update {{ nameLower }}: ${message}`);
|
||||
res.status(400).json({
|
||||
error: 'Failed to update {{ nameLower }}',
|
||||
});
|
||||
}
|
||||
},
|
||||
]);
|
||||
|
||||
app.delete('/{{ nameKebab }}/:{{ primaryKey }}', [
|
||||
isAdmin,
|
||||
async (req: RequestContext, res: Response) => {
|
||||
try {
|
||||
const {{ primaryKey }} = req.params.{{ primaryKey }};
|
||||
await {{ nameCamel }}Service.delete({{ primaryKey }});
|
||||
res.status(200);
|
||||
res.send();
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
console.error(`Failed to delete {{ nameLower }}: ${message}`);
|
||||
res.status(400).json({
|
||||
error: 'Failed to delete {{ nameLower }}',
|
||||
});
|
||||
}
|
||||
},
|
||||
]);
|
||||
|
||||
app.get('/{{ nameKebab }}/list', [
|
||||
isAdmin,
|
||||
async (req: RequestContext, res: Response) => {
|
||||
try {
|
||||
const {{ nameCamel }}s = await {{ nameCamel }}Service.getAll();
|
||||
const formatted{{ nameFirst }}s = {{ nameCamel }}s.map({{ nameCamel }}Mapper);
|
||||
res.json(formatted{{ nameFirst }}s);
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
console.error(`Failed to get {{ nameLower }}s: ${message}`);
|
||||
res.status(400).json({
|
||||
error: 'Failed to get {{ nameLower }}s',
|
||||
});
|
||||
}
|
||||
},
|
||||
]);
|
||||
|
||||
app.get('/{{ nameKebab }}/:{{ primaryKey }}', [
|
||||
isAdmin,
|
||||
async (req: RequestContext, res: Response) => {
|
||||
try {
|
||||
const {{ nameCamel }} = await {{ nameCamel }}Service.get(req.params.{{ primaryKey }});
|
||||
res.json({{ nameCamel }}Mapper({{ nameCamel }}));
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
console.error(`Failed to get {{ nameLower }}: ${message}`);
|
||||
res.status(400).json({
|
||||
error: 'Failed to get {{ nameLower }}',
|
||||
});
|
||||
}
|
||||
},
|
||||
]);
|
16
commands/add-object/template/api/blank-dynamodb.yml
Normal file
16
commands/add-object/template/api/blank-dynamodb.yml
Normal file
|
@ -0,0 +1,16 @@
|
|||
Resources:
|
||||
{{ nameCamel }}Table:
|
||||
Type: AWS::DynamoDB::Table
|
||||
DeletionPolicy: ${self:custom.deletionPolicy.${opt:stage}}
|
||||
UpdateReplacePolicy: ${self:custom.updatePolicy.${opt:stage}}
|
||||
Properties:
|
||||
TableName: ${env:APP_NAME}-${opt:stage}-{{ nameKebab }}
|
||||
AttributeDefinitions:
|
||||
- AttributeName: {{ primaryKey }}
|
||||
AttributeType: S
|
||||
KeySchema:
|
||||
- AttributeName: {{ primaryKey }}
|
||||
KeyType: HASH
|
||||
BillingMode: PAY_PER_REQUEST
|
||||
PointInTimeRecoverySpecification:
|
||||
PointInTimeRecoveryEnabled: true
|
37
commands/add-object/template/api/blank-functions.yml
Normal file
37
commands/add-object/template/api/blank-functions.yml
Normal file
|
@ -0,0 +1,37 @@
|
|||
Api{{ nameFirst }}:
|
||||
handler: src/baseblocks/{{ nameKebab }}/{{ nameKebab }}-api.handler
|
||||
events:
|
||||
- http:
|
||||
path: /{{ nameKebab }}/{any+}
|
||||
method: ANY
|
||||
authorizer: # https://www.serverless.com/framework/docs/providers/aws/events/apigateway#http-endpoints-with-aws_iam-authorizers
|
||||
type: COGNITO_USER_POOLS
|
||||
authorizerId:
|
||||
Ref: ApiGatewayAuthorizer
|
||||
cors:
|
||||
origin: ${self:custom.apiCorsOrigin}
|
||||
headers:
|
||||
- Content-Type
|
||||
- X-Amz-Date
|
||||
- Authorization
|
||||
- X-Api-Key
|
||||
- X-Amz-Security-Token
|
||||
- X-Amz-User-Agent
|
||||
allowCredentials: false
|
||||
- http:
|
||||
path: /{{ nameKebab }}
|
||||
method: ANY
|
||||
authorizer: # https://www.serverless.com/framework/docs/providers/aws/events/apigateway#http-endpoints-with-aws_iam-authorizers
|
||||
type: COGNITO_USER_POOLS
|
||||
authorizerId:
|
||||
Ref: ApiGatewayAuthorizer
|
||||
cors:
|
||||
origin: ${self:custom.apiCorsOrigin}
|
||||
headers:
|
||||
- Content-Type
|
||||
- X-Amz-Date
|
||||
- Authorization
|
||||
- X-Api-Key
|
||||
- X-Amz-Security-Token
|
||||
- X-Amz-User-Agent
|
||||
allowCredentials: false
|
3
commands/add-object/template/api/blank.seed.json
Normal file
3
commands/add-object/template/api/blank.seed.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
[
|
||||
{{ seedData }}
|
||||
]
|
14
commands/add-object/template/api/blank.service.ts
Normal file
14
commands/add-object/template/api/blank.service.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { {{ nameFirst }} } from '@baseline/types/{{ nameKebab }}';
|
||||
import { getDynamodbConnection } from '@baselinejs/dynamodb';
|
||||
import { ServiceObject } from '../../util/service-object';
|
||||
|
||||
const dynamoDb = getDynamodbConnection({
|
||||
region: `${process.env.API_REGION}`,
|
||||
});
|
||||
|
||||
export const {{ nameCamel }}Service = new ServiceObject<{{ nameFirst }}>({
|
||||
dynamoDb: dynamoDb,
|
||||
objectName: '{{ nameFirst }}',
|
||||
table: `${process.env.APP_NAME}-${process.env.NODE_ENV}-{{ nameKebab }}`,
|
||||
primaryKey: '{{ primaryKey }}',
|
||||
});
|
7
commands/add-object/template/api/blank.ts
Normal file
7
commands/add-object/template/api/blank.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { {{ nameFirst }} } from '@baseline/types/{{ nameKebab }}';
|
||||
|
||||
export const {{ nameCamel }}Mapper = (data: {{ nameFirst }}): {{ nameFirst }} => {
|
||||
const {{ nameCamel }}: {{ nameFirst }} = {{{ mapperFields }}
|
||||
};
|
||||
return {{ nameCamel }};
|
||||
};
|
70
commands/add-object/template/client-api/blank.ts
Normal file
70
commands/add-object/template/client-api/blank.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
import { {{ nameFirst }} } from '@baseline/types/{{ nameKebab }}';
|
||||
import { RequestHandler } from './request-handler';
|
||||
|
||||
export const get{{ nameFirst }} = async (requestHandler: RequestHandler, {{ nameCamel }}Id: string): Promise<{{ nameFirst }}> => {
|
||||
const response = await requestHandler.request<{{ nameFirst }}>({
|
||||
method: 'GET',
|
||||
url: `{{ nameKebab }}/${{{ nameCamel }}Id}`,
|
||||
hasAuthentication: true,
|
||||
});
|
||||
if ('data' in response) {
|
||||
return response.data;
|
||||
}
|
||||
throw response;
|
||||
};
|
||||
|
||||
export const getAll{{ nameFirst }}s = async (requestHandler: RequestHandler): Promise<{{ nameFirst }}[]> => {
|
||||
const response = await requestHandler.request<{{ nameFirst }}[]>({
|
||||
method: 'GET',
|
||||
url: `{{ nameKebab }}/list`,
|
||||
hasAuthentication: true,
|
||||
});
|
||||
if ('data' in response) {
|
||||
return response.data;
|
||||
}
|
||||
throw response;
|
||||
};
|
||||
|
||||
export const delete{{ nameFirst }} = async (requestHandler: RequestHandler, {{ nameCamel }}Id: string): Promise<boolean> => {
|
||||
const response = await requestHandler.request<boolean>({
|
||||
method: 'DELETE',
|
||||
url: `{{ nameKebab }}/${{{ nameCamel }}Id}`,
|
||||
hasAuthentication: true,
|
||||
});
|
||||
if ('data' in response) {
|
||||
return response.data;
|
||||
}
|
||||
throw response;
|
||||
};
|
||||
|
||||
export const create{{ nameFirst }} = async (
|
||||
requestHandler: RequestHandler,
|
||||
{{ nameCamel }}: Partial<{{ nameFirst }}>,
|
||||
): Promise<{{ nameFirst }}> => {
|
||||
const response = await requestHandler.request<{{ nameFirst }}>({
|
||||
method: 'POST',
|
||||
url: `{{ nameKebab }}`,
|
||||
hasAuthentication: true,
|
||||
data: {{ nameCamel }},
|
||||
});
|
||||
if ('data' in response) {
|
||||
return response.data;
|
||||
}
|
||||
throw response;
|
||||
};
|
||||
|
||||
export const update{{ nameFirst }} = async (
|
||||
requestHandler: RequestHandler,
|
||||
{{ nameCamel }}: Partial<{{ nameFirst }}>,
|
||||
): Promise<{{ nameFirst }}> => {
|
||||
const response = await requestHandler.request<{{ nameFirst }}>({
|
||||
method: 'PATCH',
|
||||
url: `{{ nameKebab }}`,
|
||||
hasAuthentication: true,
|
||||
data: {{ nameCamel }},
|
||||
});
|
||||
if ('data' in response) {
|
||||
return response.data;
|
||||
}
|
||||
throw response;
|
||||
};
|
3
commands/add-object/template/types/blank.d.ts
vendored
Normal file
3
commands/add-object/template/types/blank.d.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
export interface {{ nameFirst }} {
|
||||
{{ typeFields }}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue