Skip to content

Commit

Permalink
Merge pull request #7 from primno/dev
Browse files Browse the repository at this point in the history
Open environment url in start command
  • Loading branch information
xaviermonin authored May 1, 2023
2 parents c004cb1 + 47bb5ed commit 6136427
Show file tree
Hide file tree
Showing 12 changed files with 91 additions and 35 deletions.
6 changes: 6 additions & 0 deletions .changeset/nasty-ties-dance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@primno/cli": minor
---

Opens the environment url when the start command is executed.
Added "--no-open" option in the start command. If this option is set, the environment will not be opened in the browser.
2 changes: 1 addition & 1 deletion lib/template/new/src/list/contact.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ export class ContactComponent {
*
* To works, this event must be manually added in the command bar of `contact` table
* by calling the `mn_main.onCommandInvoke` method with the parameters:
* - A string parameter with the name `hello` (the name of the command)
* - SelectedControl
* - PrimaryControl
* - A string parameter with the name `hello` (the name of the command)
*/
@MnOnCommandInvoke("hello")
public sayHello(eventArg: CommandBarEventArg) {
Expand Down
12 changes: 9 additions & 3 deletions rollup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,16 @@ const external: string[] = [
const plugins = [
typescript({ compilerOptions: { rootDir: "./src" } }),
commonjs(),
resolve(),
terser()
resolve()
];

const watchMode = process.env.ROLLUP_WATCH === "true";
const sourcemap = watchMode ? "inline" : false;

if (!watchMode) {
plugins.push(terser());
}

export default function(
//command: Record<string, unknown>
): RollupOptions[] {
Expand All @@ -29,7 +35,7 @@ export default function(
input: 'src/index.ts',
plugins,
external,
output: { format: 'esm', file: 'dist/mn.mjs' }
output: { format: 'esm', file: 'dist/mn.mjs', sourcemap }
}
]
}
9 changes: 7 additions & 2 deletions src/commands/start-command.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import { Command } from "commander";
import { Workspace } from "../core/workspace";

async function startAction() {
interface Options {
open: boolean;
}

async function startAction(options: Options) {
if (!Workspace.isWorkspace(".")) {
console.error("This action must be run in a primno project directory");
return;
}

const currentWs = new Workspace(".");
await currentWs.start({});
await currentWs.start({ openInBrowser: options.open });
};

export const startCommand = new Command("start")
.description("deploy primno in local development mode and run a web server that watches the entry points files")
.option("--no-open", "do not open the browser", false)
.action(startAction);
6 changes: 5 additions & 1 deletion src/core/builder/bundler/bundler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Result, ResultBuilder } from "../../../task";
import { getPackageJson } from "../../../utils/package";
import { onWarnWrapper } from "./warn-wrapper";
import babel from "@rollup/plugin-babel";
import { buildMessage } from "./message-builder";

export interface BundlerOptions {
sourcePath: string;
Expand Down Expand Up @@ -120,7 +121,10 @@ export class Bundler {
resultBuilder.start();
break;
case "ERROR":
resultBuilder.addError(`${event.error.message} at ${event.error.loc?.line}, ${event.error.loc?.column}`)
{
const message = buildMessage(event.error);
resultBuilder.addError(message);
}
break;
case "END":
resultBuilder.end();
Expand Down
12 changes: 12 additions & 0 deletions src/core/builder/bundler/message-builder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import path from "path";
import { RollupError, RollupWarning } from "rollup";

export function buildMessage(source: RollupWarning | RollupError): string {
if (source.loc?.file) {
const filePath = path.relative(".", source.loc.file);
return `${source.message} from "${filePath}":${source.loc.line}:${source.loc.column}`;
}
else {
return `${source.message}`;
}
}
11 changes: 3 additions & 8 deletions src/core/builder/bundler/warn-wrapper.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import path from "path";
import { WarningHandler } from "rollup";
import { ResultBuilder } from "../../../task";
import { buildMessage } from "./message-builder";

export function onWarnWrapper(resultBuilder: ResultBuilder): WarningHandler {
return (warning) => {
if (warning.loc?.file) {
const filePath = path.relative(".", warning.loc.file);
resultBuilder.addWarning(`${warning.message} at ${filePath} [${warning.loc.line}, ${warning.loc.column}]`);
}
else {
resultBuilder.addWarning(`${warning.message}`);
}
const message = buildMessage(warning);
resultBuilder.addWarning(message);
};
}
22 changes: 16 additions & 6 deletions src/core/server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,32 @@ export interface ServeInfo {
newSelfSignedCert: boolean;
}

interface ServeOptions extends Serve {
environmentUrl: string;
}

export class Server {
private server?: http.Server | https.Server | null;

public constructor(private config: Serve) { }
public constructor(private config: ServeOptions) { }

public async serve(directory: string): Promise<ServeInfo> {
if (this.server != null) {
throw new Error("Server already started");
}

const app = express();
app.use(cors());
app.use(express.static(directory));
app.get("/", (_req, res) => {
res.send("Primno: Development server is ready.");
});
app
.use(cors())
.use("build", express.static(directory))
.get("/", (_req, res) => {
res.send(`<h1>Primno</h1><p>Development server is ready.</p>` +
`<p>Navigate to the <a href="/redirect">D365 / Power Apps environment</a>.</p>`
);
})
.get("/redirect", (_req, res) => {
res.redirect(this.config.environmentUrl);
});

let newSelfSignedCert = false;

Expand Down
25 changes: 19 additions & 6 deletions src/core/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Publisher } from "./deployer/publisher";
import { map, Observable } from "rxjs";
import { Action, Task, ResultBuilder } from "../task";
import open from "open";
import { getEnvironmentUrl } from "../utils/dataverse-client";

interface EntryPointOptions {
entryPoint?: string | string[];
Expand All @@ -34,8 +35,12 @@ export interface WatchOptions extends BuildOptions {

}

export interface StartOptions extends EntryPointOptions {
export interface StartOptions extends EntryPointOptions, ServeOptions {

}

export interface ServeOptions {
openInBrowser: boolean;
}

export interface PublishOptions {
Expand Down Expand Up @@ -192,33 +197,41 @@ export class Workspace {
production: false,
mode: EntryPointBuildMode.primnoImportLocal
}), "Deploy")
.addSubtasks(this.serveTask())
.addSubtasks(this.serveTask({ openInBrowser: options.openInBrowser }))
.addSubtasks(this.watchTask({
entryPoint: options.entryPoint,
mode: EntryPointBuildMode.moduleOnly,
production: false,
}));
}

private serveTask(): Task {
private serveTask(options: ServeOptions): Task {
return Task.new()
.newAction({
title: "Serve",
action: async () => {
const server = new Server(this.config.serve as Serve);
const server = new Server({
...this.config.serve,
environmentUrl: getEnvironmentUrl(this.environment?.connectionString!)
});

const serveInfo = await server.serve(this.config.distDir);

const resultBuilder = new ResultBuilder();
const url = `${serveInfo.schema}://localhost:${serveInfo.port}/`;
const redirectUrl = `${url}redirect`;
resultBuilder.addInfo(`Serving on ${url}`);

if (serveInfo.newSelfSignedCert) {
resultBuilder.addWarning(`New self-signed certificate generated. Accept it in your browser.`);
}

if (options.openInBrowser) {
try {
await open(url);
await open(redirectUrl);
}
catch {
resultBuilder.addWarning(`Unable to open browser. Please open ${url} manually.`);
resultBuilder.addWarning(`Unable to open browser. Please open ${redirectUrl} manually.`);
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ program
.addCommand(buildCommand)
.addCommand(watchCommand)
.addCommand(deployCommand)
.parseAsync(process.argv);
.parseAsync(process.argv)
.catch((err) => {
process.exitCode = 1;
});
7 changes: 2 additions & 5 deletions src/task/task.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Listr, ListrTask } from "listr2";
import { Observable } from "rxjs";
import { ActionHandler, TaskInfo, TaskType } from "./task-info";
import { exitCode } from "process";

export interface Action {
title: string;
Expand Down Expand Up @@ -228,10 +229,6 @@ export class Task {
*/
public async run() {
const listR = this.getListR();

try {
await listR.run();
}
catch (except) {}
await listR.run();
}
}
9 changes: 7 additions & 2 deletions src/utils/dataverse-client.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { ConnStringTokenProvider } from "@primno/dataverse-auth";
import { ConnStringTokenProvider, ConnectionString } from "@primno/dataverse-auth";
import { DataverseClient } from "@primno/dataverse-client";

const clients: { [key: string]: DataverseClient } = {};

export function getClient(connectionString: string,deviceCodeCallback: (url: string, code: string) => void): DataverseClient {
export function getEnvironmentUrl(cs: string): string {
const connectionString = new ConnectionString(cs);
return connectionString.serviceUri!;
}

export function getClient(connectionString: string, deviceCodeCallback: (url: string, code: string) => void): DataverseClient {
if (clients[connectionString] == null) {
const csClient = new ConnStringTokenProvider(
connectionString,
Expand Down

0 comments on commit 6136427

Please sign in to comment.