-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(cli): connect Vuejs project with client's cloud org #43
Changes from 11 commits
18490ef
264057b
9958c8f
215640b
8ab23e7
701057b
71b41dd
b879421
0e6f7af
935b5e3
35d5d66
f8d9763
4500e9f
6b9dadf
32c3469
bcb28fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,17 @@ | ||
{ | ||
"useConfigFiles": true, | ||
"plugins": { | ||
"@vue/cli-plugin-babel": {}, | ||
"@vue/cli-plugin-typescript": { | ||
"classComponent": true, | ||
"useTsWithBabel": true | ||
"classComponent": true | ||
}, | ||
"@vue/cli-plugin-router": { | ||
"historyMode": true | ||
}, | ||
"@vue/cli-plugin-eslint": { | ||
"config": "standard", | ||
"lintOn": ["save", "commit"] | ||
"lintOn": ["commit"] | ||
} | ||
}, | ||
"cssPreprocessor": "node-sass", | ||
"vueVersion": "2" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,13 @@ | ||
import {Command, flags} from '@oclif/command'; | ||
import {dirname, resolve} from 'path'; | ||
import {resolve} from 'path'; | ||
import { | ||
buildAnalyticsFailureHook, | ||
buildAnalyticsSuccessHook, | ||
} from '../../../hooks/analytics/analytics'; | ||
import {Config} from '../../../lib/config/config'; | ||
import AuthenticationRequired from '../../../lib/decorators/authenticationRequired'; | ||
import {Storage} from '../../../lib/oauth/storage'; | ||
import {platformUrl} from '../../../lib/platform/environment'; | ||
import {spawnProcess} from '../../../lib/utils/process'; | ||
|
||
export default class Vue extends Command { | ||
|
@@ -19,7 +23,6 @@ export default class Vue extends Command { | |
'If not specified, the default TypeScript preset will be taken.', | ||
'For more information about Vue CLI presets, please consult https://cli.vuejs.org/guide/plugins-and-presets.html#presets', | ||
].join('\n'), | ||
// default: TODO: add default preset once it is available in npm https://coveord.atlassian.net/browse/CDX-39 | ||
}), | ||
}; | ||
|
||
|
@@ -32,6 +35,7 @@ export default class Vue extends Command { | |
{name: 'name', description: 'application name', required: true}, | ||
]; | ||
|
||
@AuthenticationRequired() | ||
async run() { | ||
const {args, flags} = this.parse(Vue); | ||
|
||
|
@@ -45,9 +49,7 @@ export default class Vue extends Command { | |
} | ||
} | ||
await this.createProject(args.name, preset); | ||
await this.installPlugin(args.name); | ||
await this.invokePlugin(args.name); | ||
this.startServer(args.name); | ||
await this.config.runHook( | ||
'analytics', | ||
buildAnalyticsSuccessHook(this, flags) | ||
|
@@ -63,48 +65,50 @@ export default class Vue extends Command { | |
throw err; | ||
} | ||
|
||
private installPlugin(applicationName: string) { | ||
// TODO: DELETE THIS METHOD ONCE THE PLUGIN IS PUBLISHED AND PART OF THE PRESET | ||
// CDX-39 | ||
// Once the coveo plugin is published to npm, simply include it in the preset typescript-preset.json | ||
// This will prevent from running `2 npm install` commands (one by @vue/cli, one for the plugin) | ||
const pathToPlugin = dirname(require.resolve('vue-cli-plugin-coveo')); | ||
return spawnProcess( | ||
'npm', | ||
['install', '--save-dev', `file:${pathToPlugin}`], | ||
{ | ||
cwd: applicationName, | ||
} | ||
); | ||
} | ||
private async invokePlugin(applicationName: string) { | ||
const cfg = await this.configuration.get(); | ||
const storage = await this.storage.get(); | ||
|
||
private invokePlugin(applicationName: string) { | ||
return this.runVueCliCommand(['invoke', 'vue-cli-plugin-coveo'], { | ||
const cliArgs = [ | ||
'invoke', | ||
'@coveo/vue-cli-plugin-typescript', | ||
'--orgId', | ||
cfg.organization, | ||
'--apiKey', | ||
storage.accessToken!, | ||
'--platformUrl', | ||
platformUrl({environment: cfg.environment}), | ||
// TODO: CDX-91 Extract user email from oauth flow | ||
'--user', | ||
'[email protected]', | ||
]; | ||
|
||
return this.runVueCliCommand(cliArgs, { | ||
cwd: applicationName, | ||
}); | ||
} | ||
|
||
private startServer(applicationName: string) { | ||
// TODO: DELETE THIS METHOD ONCE THE PLUGIN IS PUBLISHED AND PART OF THE PRESET | ||
// The @vue/cli already logs instructions once the installation completes | ||
this.log(`Successfully created project ${applicationName}.`); | ||
this.log('Get started with the following commands:\n'); | ||
|
||
this.log('$ cd ${applicationName}'); | ||
this.log('$ yarn serve'); | ||
} | ||
|
||
private createProject(name: string, preset: {}) { | ||
return this.runVueCliCommand([ | ||
'create', | ||
name, | ||
'--inlinePreset', | ||
JSON.stringify(preset), | ||
'--skipGetStarted', | ||
'--bare', | ||
]); | ||
} | ||
|
||
private runVueCliCommand(args: string[], options = {}) { | ||
const executable = require.resolve('@vue/cli/bin/vue.js'); | ||
return spawnProcess(executable, args, options); | ||
} | ||
|
||
private get configuration() { | ||
return new Config(this.config.configDir, this.error); | ||
} | ||
|
||
private get storage() { | ||
return new Storage(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,21 @@ | ||
// eslint-disable-next-line no-unused-vars | ||
module.exports = (api, options, rootOptions) => { | ||
api.extendPackage({ | ||
scripts: { | ||
postinstall: 'node ./scripts/setup-server.js', | ||
start: 'concurrently --raw "npm run start-server" "npm run serve"', | ||
'start-server': 'node ./scripts/start-server.js', | ||
}, | ||
dependencies: { | ||
'@coveo/headless': '^0.1.0', | ||
'@coveo/search-token-server': | ||
'file:/Users/ylakhdar/Repos/coveo-cli/packages/search-token-server/search-token-server-0.0.0.tgz', | ||
y-lakhdar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
buefy: '^0.9.4', | ||
}, | ||
devDependencies: { | ||
'node-sass': '^5.0.0', | ||
'sass-loader': '^10.1.1', | ||
concurrently: '^5.3.0', | ||
}, | ||
}); | ||
|
||
api.render('./template', { | ||
// TODO: inject the appropriate file type | ||
...rootOptions, | ||
...options, | ||
}); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# <%- rootOptions.projectName %> | ||
|
||
## Project setup | ||
|
||
``` | ||
npm install | ||
``` | ||
|
||
### Compiles and hot-reloads for development | ||
|
||
``` | ||
npm start | ||
``` | ||
|
||
### Compiles and minifies for production | ||
|
||
``` | ||
npm run build | ||
``` | ||
|
||
### Lints and fixes files | ||
|
||
``` | ||
npm run lint | ||
``` | ||
|
||
### Customize configuration | ||
|
||
See [Configuration Reference](https://cli.vuejs.org/config/). |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
VUE_APP_PLATFORM_URL=<%- options.platformUrl -%> | ||
|
||
VUE_APP_ORGANIZATION_ID=<%- options.orgId -%> | ||
|
||
VUE_APP_API_KEY=<%- options.apiKey -%> | ||
|
||
VUE_APP_USER_EMAIL=<%- options.user -%> | ||
|
||
VUE_APP_TOKEN_ENDPOINT="/token" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# The Plaform URL to use. | ||
# See https://docs.coveo.com/en/2976/coveo-solutions/deployment-regions-and-strategies | ||
VUE_APP_PLATFORM_URL=https://platform.cloud.coveo.com | ||
|
||
# The unique identifier of the organization in which to generate a search token. | ||
# Example: VUE_APP_ORGANIZATION_ID=mycoveoorganizationg8tp8wu3. | ||
# See https://docs.coveo.com/en/148/manage-an-organization/retrieve-the-organization-id | ||
VUE_APP_ORGANIZATION_ID=<YOUR_ORGANIZATION_ID> | ||
|
||
# An API key granting the impersonate privilege in your organization. | ||
# The API key should have the impersonate privilege. | ||
# See https://docs.coveo.com/en/1718/manage-an-organization/manage-api-keys#add-an-api-key | ||
VUE_APP_API_KEY=<YOUR_API_KEY> | ||
|
||
# The name of the security identity to impersonate. | ||
# Example: VUE_APP_USER_EMAIL="[email protected]" | ||
# See https://docs.coveo.com/en/56/#name-string-required. | ||
VUE_APP_USER_EMAIL=<YOUR_USER_EMAIL> | ||
|
||
# The path to the server returning Coveo search tokens. | ||
# By default, it targets server on the same host. | ||
VUE_APP_TOKEN_ENDPOINT="/token" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
const {spawnSync} = require('child_process'); | ||
const {copySync} = require('fs-extra'); | ||
const {sep, resolve} = require('path'); | ||
|
||
function installSearchTokenServerDependencies() { | ||
const child = spawnSync('npm', ['install'], { | ||
stdio: 'inherit', | ||
cwd: resolve('server'), | ||
}); | ||
if (child.status !== 0) { | ||
process.exit(child.status); | ||
} | ||
} | ||
|
||
function isNodeModule(path) { | ||
return path.split(sep).indexOf('node_modules') !== -1; | ||
} | ||
|
||
function isEnvFile(path) { | ||
return path.split(sep).indexOf('.env.example') !== -1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure about this function. The condition for a file to be an envFile would be imo: /.env$/.test(path); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I'll rename it to be And that's because the |
||
} | ||
|
||
function copySearchTokenServerToRoot() { | ||
copySync( | ||
resolve('node_modules', '@coveo', 'search-token-server'), | ||
resolve('server'), | ||
{ | ||
filter: (src, dest) => !isNodeModule(dest) && !isEnvFile(dest), | ||
} | ||
); | ||
} | ||
|
||
function main() { | ||
copySearchTokenServerToRoot(); | ||
installSearchTokenServerDependencies(); | ||
} | ||
|
||
main(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
const {spawnSync} = require('child_process'); | ||
const {resolve, join} = require('path'); | ||
const {config} = require('dotenv'); | ||
config(); | ||
|
||
function getEnvVariables() { | ||
// TODO: CDX-99: assign port dynamically | ||
// The Vue CLi has a --proxy flag. | ||
const searchTokenServerPort = 4000; | ||
var envVars = Object.assign( | ||
{ | ||
SERVER_PORT: searchTokenServerPort, | ||
API_KEY: process.env.VUE_APP_API_KEY, | ||
ORGANIZATION_ID: process.env.VUE_APP_ORGANIZATION_ID, | ||
PLATFORM_URL: process.env.VUE_APP_PLATFORM_URL, | ||
USER_EMAIL: process.env.VUE_APP_USER_EMAIL, | ||
}, | ||
process.env | ||
); | ||
return envVars; | ||
} | ||
|
||
function startServer() { | ||
const serverPath = join(process.cwd(), 'server'); | ||
const child = spawnSync('npm', ['run', 'start'], { | ||
stdio: 'inherit', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we OK with mixing up stdio of npm run serve and the server? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well we want to make it easy for the user. |
||
env: getEnvVariables(), | ||
cwd: resolve(serverPath), | ||
}); | ||
if (child.status !== 0) { | ||
process.exit(child.status); | ||
} | ||
} | ||
|
||
function main() { | ||
startServer(); | ||
} | ||
|
||
main(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,3 @@ | ||
<template> | ||
<div id="app"> | ||
<div class="hero is-primary is-medium"> | ||
<Hero msg="Welcome to Your Coveo Vue.js Search Page" /> | ||
</div> | ||
<SearchPage /> | ||
</div> | ||
<router-view /> | ||
</template> | ||
|
||
<script lang="ts"> | ||
import {Component, Vue} from 'vue-property-decorator'; | ||
import Hero from './components/Hero.vue'; | ||
import SearchPage from './components/SearchPage.vue'; | ||
|
||
@Component({ | ||
components: { | ||
Hero, | ||
SearchPage, | ||
}, | ||
}) | ||
export default class App extends Vue {} | ||
</script> | ||
|
||
<style lang="scss"> | ||
#app { | ||
font-family: $family-primary; | ||
-webkit-font-smoothing: antialiased; | ||
-moz-osx-font-smoothing: grayscale; | ||
text-align: center; | ||
color: $primary !important; | ||
} | ||
</style> |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does --skipGetStarted and --bare options do ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
--bare
: Scaffold project without beginner instructions on the home page. There is no point in having them because we override the home page with the search page.--skipGetStarted
: Skip displaying "Get started" instructions. We don't want thecreate
command to display theTo get started, cd myproject && yarn serve
message because the Coveo template was not invoked yet. The creation of a Coveo project is a 2 step process:vue create project
vue invoke @coveo/typescript
Ideally, we want to display a nice get-started message after our template is invoked.