Skip to content

Commit

Permalink
Cli update (#25)
Browse files Browse the repository at this point in the history
* remove sdk from cli

* update playground middleware

* refactor exampleEndpoint to exampleMethod

* update cli for nuxt

* remove test method

* update cli for next

* remove test endpoints
  • Loading branch information
WojtekTheWebDev authored Mar 13, 2024
1 parent ef47d50 commit 59d826e
Show file tree
Hide file tree
Showing 28 changed files with 381 additions and 439 deletions.
6 changes: 6 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
module.exports = {
extends: "@vue-storefront/eslint-config-integrations",
rules: {
"@typescript-eslint/no-unused-vars": "warn",
"import/no-relative-packages": "off",
"@typescript-eslint/no-empty-function": "off",
"import/extensions": "off",
},
};
25 changes: 13 additions & 12 deletions cli/build.config.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { defineBuildConfig } from 'unbuild'
// eslint-disable-next-line import/no-unresolved
import { defineBuildConfig } from "unbuild";

export default defineBuildConfig({
rollup: {
inlineDependencies: true,
},
entries: ['src/index'],
entries: ["src/index"],
externals: [
'citty',
'fsevents',
'node:url',
'node:buffer',
'node:path',
'node:child_process',
'node:process',
'node:path',
'node:os',
"citty",
"fsevents",
"node:url",
"node:buffer",
"node:path",
"node:child_process",
"node:process",
"node:path",
"node:os",
],
})
});
4 changes: 2 additions & 2 deletions cli/cli.config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export const config = {
integrationName: "boilerplate"
}
integrationName: "boilerplate",
};
227 changes: 82 additions & 145 deletions cli/dist/chunks/add.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import fs, { existsSync, promises } from 'fs';
import { createConsola } from 'consola';
import { defineCommand } from 'citty';
import { Project } from 'ts-morph';

function normalizeWindowsPath(input = "") {
if (!input || !input.includes("\\")) {
Expand Down Expand Up @@ -112,91 +111,72 @@ const config = {
const nuxtPageMethod = ({ name }) => ({
path: `playground/app/pages/methods/${name}.vue`,
contents: `
<template>
<div class="flex justify-center items-center h-screen">
<div class="p-5 w-96">
<h1 class="typography-headline-2 font-bold mt-2 mb-4 text-green-500">
Build something amazing
</h1>
<p class="text-gray-50">
${config.integrationName}/${name}
</p>
<div class="box">
<!-- <JsonViewer :value="jsonData" copyable boxed sort theme="light" @onKeyClick="keyClick"/> -->
<h4 class="text-gray-50">Response</h4>
<JsonViewer class="min-h-[800px] min-w-[500px]" :value="res" expandDepth="5" expanded copyable boxed sort
theme="dark" />
</div>
<div class="flex flex-col md:flex-row gap-4 mt-6">
<SfButton @click="callEndpoint" size="lg"> call </SfButton>
<SfButton @click="reset" size="lg" variant="secondary" class="bg-white"> reset </SfButton>
</div>
</div>
<template>
<div class="flex justify-center items-center h-screen">
<div class="p-5 w-96">
<h1 class="typography-headline-2 font-bold mt-2 mb-4 text-green-500">
Build something amazing
</h1>
<p class="text-gray-50">${config.integrationName}/${name}</p>
<div class="box">
<!-- <JsonViewer :value="jsonData" copyable boxed sort theme="light" @onKeyClick="keyClick"/> -->
<h4 class="text-gray-50">Response</h4>
<JsonViewer
class="min-h-[800px] min-w-[500px]"
:value="res"
expandDepth="5"
expanded
copyable
boxed
sort
theme="dark"
/>
</div>
<div class="flex flex-col md:flex-row gap-4 mt-6">
<SfButton @click="callEndpoint" size="lg"> call </SfButton>
<SfButton @click="reset" size="lg" variant="secondary" class="bg-white">
reset
</SfButton>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { SfButton } from '@storefront-ui/vue';
import { sdk } from '~/sdk.config';
import { JsonViewer } from "vue3-json-viewer"
import { SfButton } from "@storefront-ui/vue";
import { JsonViewer } from "vue3-json-viewer";
import "vue3-json-viewer/dist/index.css";
const res = useState('waiting to call ${name} ...');
const sdk = useSdk();
const res = useState(
"${name}",
() => "waiting to call ${name}() ..."
);
async function callEndpoint() {
const { data } = await sdk.${config.integrationName}.${name}('test');
res.value = data
const { data } = await sdk.${config.integrationName}.${name}("test");
res.value = data;
}
function reset() {
res.value = 'waiting to call ${name} ...'
res.value = "waiting to call test ...";
}
<\/script>
`
});

const sdkMethod = ({ name }) => ({
path: `packages/sdk/src/methods/${name}/index.ts`,
contents: `import { client } from '../../client';
import { TODO } from '../../types';
/**
* Method summary - General information about the SDK method, usually a single sentence.
*
* @remarks
* In this section, we have been adding detailed information such as:
* * what API middleware endpoint this method is calling,
* * what SAP OCC API endpoints are being called as a result of using this method,
* * when this method can be used and when it can\u2019t (e.g. logged-in vs anonymous users),
* * simply everything what helps with understanding how it works.
*
* @param props
* Just like our API methods, our SDK connector methods accept a single props parameter which carries relevant sub-properties. Therefore, there isn\u2019t much to be described within that TSDoc section.
*
* @returns
* Human-friendly information what the SDK methods returns.
*
* @example
* A short code snippet showing how to use the method. Usually we have more than one @example. We should strive for adding as many examples as possible here, with multiple param configurations.
*/
export async function ${name}(props: TODO) {
const { data } = await client.post<TODO>('${name}', props);
return data
}
`
});

const apiMethod = ({ name }) => ({
path: `packages/api-client/src/api/${name}/index.ts`,
contents: `import { Endpoints } from '../../types';
contents: `import consola from "consola";
import { BoilerplateIntegrationContext, TODO } from "../../types";
export const ${name}: Endpoints['${name}'] = async (
context,
params
export const ${name} = async (
context: BoilerplateIntegrationContext,
params: TODO
) => {
console.log('${name} has been called');
consola.log("${name} has been called");
return { data: 'Hello from ${name} endpoint!' };
return { data: "Hello from ${name} endpoint!" };
};
`
});
Expand All @@ -207,40 +187,39 @@ function capitalizeFirst(input) {

const nextPageMethod = ({ name }) => ({
path: `playground/app/src/pages/methods/${name}.tsx`,
contents: `import { useState } from 'react';
import { sdk } from '@/pages/_app';
import { SfButton } from '@storefront-ui/react';
import { RenderJson } from '@/components/RenderJson';
export default function Page${capitalizeFirst(name)}() {
const [data, setData] = useState<null | Object>(null);
const hitExampleMethodApi = async () => {
const data = await sdk.${config.integrationName}.${name}('test');
setData(data);
};
return (
<>
<main className="flex flex-col items-center py-24 gap-12 text-white">
<SfButton type="button" onClick={hitExampleMethodApi}>
Call ${name}
</SfButton>
<div className="w-[500px] h-min-12 h-auto p-4 bg-gray-900 rounded-md flex items-center justify-center">
{!data ? 'Click the button' : <RenderJson json={data} />}
</div>
</main>
</>
);
}
contents: `import { useState } from "react";
import { SfButton } from "@storefront-ui/react";
import { RenderJson } from "@/components/RenderJson";
import { getSdk } from "@/sdk";
export default function Page${capitalizeFirst(name)}() {
const sdk = getSdk();
const [data, setData] = useState<null | Object>(null);
const hit${capitalizeFirst(name)}Api = async () => {
const data = await sdk.${config.integrationName}.${name}("test");
setData(data);
};
return (
<>
<main className="flex flex-col items-center py-24 gap-12 text-white">
<SfButton type="button" onClick={hit${capitalizeFirst(name)}Api}>
Call ${name}
</SfButton>
<div className="w-[500px] h-min-12 h-auto p-4 bg-gray-900 rounded-md flex items-center justify-center">
{!data ? "Click the button" : <RenderJson json={data} />}
</div>
</main>
</>
);
}
`
});

const templates = {
apiMethod,
sdkMethod,
nuxtPageMethod,
nextPageMethod
};
Expand Down Expand Up @@ -269,55 +248,13 @@ function getPlaygroundFramework(playgroundPath) {
return noFramework;
}

const writeSDKMethod = async (endpoint) => {
const sdkMethodPath = `./packages/sdk/src/methods/${endpoint}`;
const isFileExist = fs.existsSync(sdkMethodPath);
if (isFileExist) {
fs.appendFileSync(
"./packages/sdk/src/methods/index.ts",
`
export { ${endpoint} } from './${endpoint}';`
);
}
};

const writeToTypescriptFile = (path, endpoint) => {
const fileName = path;
const endpointName = endpoint;
const contextType = "BoilerplateIntegrationContext";
const paramsType = "TODO";
const returnType = "TODO";
const project = new Project();
const sourceFile = project.addSourceFileAtPath(fileName);
const endpointsInterface = sourceFile.getInterface("Endpoints");
if (!endpointsInterface) {
console.error(`The "Endpoints" interface was not found in ${fileName}`);
process.exit(1);
}
const existingEndpoint = endpointsInterface.getMethod(endpointName);
if (existingEndpoint) {
existingEndpoint.remove();
}
endpointsInterface.addMethod({
name: endpointName,
parameters: [
{ name: "context", type: contextType },
{ name: "params", type: paramsType }
],
returnType: `Promise<${returnType}>`
});
sourceFile.saveSync();
};

const writeApiMethod = async (endpoint) => {
const apiIndexPath = resolve(`./packages/api-client/src/api/index.ts`);
const typesMethodPath = resolve("./packages/api-client/src/types/api/endpoints.ts");
fs.appendFileSync(
apiIndexPath,
`
export { ${endpoint} } from './${endpoint}';`
`export { ${endpoint} } from "./${endpoint}";
`
);
writeToTypescriptFile(typesMethodPath, endpoint);
};

const consola = createConsola({ fancy: true });
Expand Down Expand Up @@ -351,9 +288,8 @@ const add = defineCommand({
}
},
async run(ctx) {
const entity = ctx.args.entity;
const name = ctx.args.name;
ctx.args.cwd || resolve("./playground/app");
const { entity } = ctx.args;
const { name } = ctx.args;
const entityOptions = ["endpoint"];
if (!entityOptions.includes(entity)) {
consola.error(
Expand All @@ -368,9 +304,7 @@ const add = defineCommand({
const isForce = ctx.args.force;
if (entity === "endpoint") {
makeTemplate("apiMethod", name, isForce);
makeTemplate("sdkMethod", name, isForce);
writeApiMethod(name);
writeSDKMethod(name);
if (playgroundFramework === "next") {
makeTemplate("nextPageMethod", name, isForce);
}
Expand Down Expand Up @@ -398,7 +332,9 @@ async function makeTemplate(template, name, force = false) {
const path = resolve(res.path);
if (!force && existsSync(path)) {
consola.error(`File already exists: ${prettyPath}`);
consola.box("\u{1F699} beep beep! We did't want to risk overwriting your awesome code. \n To overwrite this path \u261D\uFE0F Use --force");
consola.box(
"\u{1F699} beep beep! We did't want to risk overwriting your awesome code. \n To overwrite this path \u261D\uFE0F Use --force"
);
process.exit(1);
}
const parentDir = dirname(path);
Expand All @@ -408,7 +344,8 @@ async function makeTemplate(template, name, force = false) {
}
await promises.mkdir(parentDir, { recursive: true });
}
await promises.writeFile(path, res.contents.trim() + "\n");
await promises.writeFile(path, `${res.contents.trim()}
`);
consola.log(`\u{1FA84} Generated a new ${template}`);
}

Expand Down
4 changes: 2 additions & 2 deletions cli/dist/chunks/call.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ const call = defineCommand({
}
},
async run(ctx) {
const endpoint = ctx.args.endpoint;
console.log("todo: make a call" + endpoint);
const { endpoint } = ctx.args;
console.log(`todo: make a call${endpoint}`);
}
});

Expand Down
Loading

0 comments on commit 59d826e

Please sign in to comment.