mirror of
https://github.com/akveo/ngx-admin.git
synced 2025-12-16 15:40:11 +01:00
fix(app):redirect after 404
This commit is contained in:
parent
74c617dc80
commit
a769ca67f5
10 changed files with 278 additions and 1 deletions
7
docs/versions.json
Normal file
7
docs/versions.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
[
|
||||
{
|
||||
"checkoutTarget": "gh-pages-deploy-fix",
|
||||
"path": "/ngx-admin/",
|
||||
"isCurrent": true
|
||||
}
|
||||
]
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
"docs": "compodoc -p src/tsconfig.app.json -d docs",
|
||||
"docs:build": "npm run build -- docs --prod --aot --base-href /ngx-admin/",
|
||||
"docs:serve": "npm start -- docs --port 4100",
|
||||
"docs:gh-pages": "npm run docs:build && npm run ngh -- --dir ./docs/dist",
|
||||
"docs:gh-pages": "ts-node -P ./scripts/docs/tsconfig.json ./scripts/docs/build-docs.ts",
|
||||
"prepush": "npm run lint:ci",
|
||||
"release:changelog": "npm run conventional-changelog -- -p angular -i CHANGELOG.md -s",
|
||||
"postinstall": "ngcc --properties es2015 es5 browser module main --first-only --create-ivy-entry-points"
|
||||
|
|
|
|||
123
scripts/docs/build-docs.ts
Normal file
123
scripts/docs/build-docs.ts
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
import { join } from 'path';
|
||||
import { copy, mkdirp, remove, outputFile, writeJson, readJson } from 'fs-extra';
|
||||
|
||||
import { generateGithubSpaScript } from './ghspa-template';
|
||||
import { runCommand } from './run-command';
|
||||
import { log } from './log';
|
||||
|
||||
import { REPO_URL, OUT_DIR, REPO_OWNER, REPO_NAME } from './config';
|
||||
const WORK_DIR = join(process.cwd(), '../_DOCS_BUILD_WORK_DIR_');
|
||||
const MASTER_BRANCH_DIR = join(WORK_DIR, 'MASTER');
|
||||
const DOCS_VERSIONS_PATH = join(MASTER_BRANCH_DIR, 'docs/versions.json');
|
||||
|
||||
export interface Version {
|
||||
checkoutTarget: string;
|
||||
name: string;
|
||||
path: string;
|
||||
isCurrent?: boolean;
|
||||
}
|
||||
|
||||
(async function () {
|
||||
log(`Cleaning work dir "${WORK_DIR}"`);
|
||||
await remove(WORK_DIR);
|
||||
log(`Cleaning output dir "${OUT_DIR}"`);
|
||||
await remove(OUT_DIR);
|
||||
|
||||
log(`Creating work dir "${WORK_DIR}"`);
|
||||
await mkdirp(WORK_DIR);
|
||||
|
||||
log(`Cloning ${REPO_URL} into ${MASTER_BRANCH_DIR}`);
|
||||
await runCommand(`git clone ${REPO_URL} ${MASTER_BRANCH_DIR}`, { cwd: WORK_DIR });
|
||||
|
||||
log('Reading versions configuration');
|
||||
const config: Version[] = await import(DOCS_VERSIONS_PATH);
|
||||
ensureSingleCurrentVersion(config);
|
||||
|
||||
log(`Versions configuration:`);
|
||||
const jsonConfig = JSON.stringify(config, null, ' ');
|
||||
log(jsonConfig);
|
||||
|
||||
log(`Building docs`);
|
||||
await buildDocs(config);
|
||||
|
||||
log(`Adding versions.json to ${OUT_DIR}`);
|
||||
await outputFile(join(OUT_DIR, 'versions.json'), jsonConfig);
|
||||
|
||||
log(`Deploying to ghpages`);
|
||||
await deploy(OUT_DIR);
|
||||
|
||||
log(`Cleaning up working directory (${WORK_DIR})`);
|
||||
await remove(WORK_DIR);
|
||||
}());
|
||||
|
||||
function ensureSingleCurrentVersion(versions: Version[]) {
|
||||
const currentVersion = versions.filter(v => v.isCurrent);
|
||||
if (currentVersion.length !== 1) {
|
||||
throw new Error(`Versions config error: Only one current version allowed.`)
|
||||
}
|
||||
}
|
||||
|
||||
async function buildDocs(versions: Version[]) {
|
||||
const ghspaScript = generateGithubSpaScript(versions);
|
||||
|
||||
return Promise.all(versions.map((version: Version) => {
|
||||
const versionDistDir = version.isCurrent
|
||||
? OUT_DIR
|
||||
: join(OUT_DIR, version.name);
|
||||
|
||||
return prepareVersion(version, versionDistDir, ghspaScript);
|
||||
}));
|
||||
}
|
||||
|
||||
async function prepareVersion(version: Version, distDir: string, ghspaScript: string) {
|
||||
const projectDir = join(WORK_DIR, `${version.name}`);
|
||||
|
||||
await copyToBuildDir(MASTER_BRANCH_DIR, projectDir);
|
||||
await checkoutVersion(version.checkoutTarget, projectDir);
|
||||
await runCommand('npm install', { cwd: projectDir });
|
||||
await addVersionNameToPackageJson(version.name, join(projectDir, 'package.json'));
|
||||
await buildDocsApp(projectDir, version.path);
|
||||
await copy(join(projectDir, 'docs/dist'), distDir);
|
||||
await outputFile(join(distDir, 'assets/ghspa.js'), ghspaScript);
|
||||
|
||||
await remove(projectDir);
|
||||
}
|
||||
|
||||
async function copyToBuildDir(from: string, to: string) {
|
||||
try {
|
||||
await mkdirp(to);
|
||||
await copy(from, to);
|
||||
} catch (e) {
|
||||
throw new Error(`Error copying from ${from} to ${to}: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function checkoutVersion(checkoutTarget: string, repoDirectory: string) {
|
||||
try {
|
||||
await runCommand(`git checkout ${checkoutTarget}`, { cwd: repoDirectory, showLog: false });
|
||||
} catch (e) {
|
||||
throw new Error(`Error checking out ${checkoutTarget}: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function addVersionNameToPackageJson(versionName: string, packageJsonPath: string) {
|
||||
const packageJsonObject = await readJson(packageJsonPath);
|
||||
packageJsonObject.versionName = versionName;
|
||||
await writeJson(packageJsonPath, packageJsonObject);
|
||||
}
|
||||
|
||||
async function buildDocsApp(projectDir: string, baseHref: string) {
|
||||
if (!baseHref.endsWith('/')) {
|
||||
baseHref = baseHref + '/';
|
||||
}
|
||||
await runCommand('npm run docs:prepare', { cwd: projectDir });
|
||||
await runCommand(`npm run build -- docs --prod --base-href '${baseHref}'`, { cwd: projectDir });
|
||||
await runCommand('npm run docs:dirs', { cwd: projectDir });
|
||||
}
|
||||
|
||||
async function deploy(distDir: string) {
|
||||
await runCommand(
|
||||
`npx angular-cli-ghpages --dir . --repo=https://GH_TOKEN@github.com/${REPO_OWNER}/${REPO_NAME}.git`,
|
||||
{ cwd: distDir, showLog: true },
|
||||
);
|
||||
}
|
||||
4
scripts/docs/config.ts
Normal file
4
scripts/docs/config.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export const REPO_URL = 'https://github.com/akveo/ngx-admin.git';
|
||||
export const REPO_OWNER = 'akveo';
|
||||
export const REPO_NAME = 'ngx-admin';
|
||||
export const OUT_DIR = 'docs/dist'; // Relative to the directory you run command
|
||||
78
scripts/docs/ghspa-template.ts
Normal file
78
scripts/docs/ghspa-template.ts
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
import { Version } from './build-docs';
|
||||
|
||||
function removeTrailingSlash(path: string): string {
|
||||
if (path.endsWith('/')) {
|
||||
return path.slice(0, -1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
export function generateGithubSpaScript(versionsToRedirect: Version[]): string {
|
||||
const paths: string[] = versionsToRedirect.map(v => v.path).map(removeTrailingSlash);
|
||||
|
||||
return `
|
||||
/**
|
||||
*
|
||||
* ____ _ ___ _ _ _ _ ___ ___ ____ ____ ____ ____ ____ ___ ____
|
||||
* | __ | | |__| | | |__] |__] |__| | __ |___ [__ [__ |__] |__|
|
||||
* |__] | | | | |__| |__] | | | |__] |___ ___] ___] | | |
|
||||
*
|
||||
* Easy way to enable Single Page Applications for GitHub Pages
|
||||
*
|
||||
* This project was released under MIT license.
|
||||
*
|
||||
* @link https://github.com/rafrex/spa-github-pages
|
||||
* @author Rafael Pedicini <code@rafrex.com>
|
||||
* @link http://websemantics.ca
|
||||
* @author Adnan M.Sagar, PhD. <adnan@websemantics.ca>
|
||||
*
|
||||
* @param {Object} l, the document current location
|
||||
* @param {Boolean} projectPages, true by default, https://help.github.com/articles/user-organization-and-project-pages
|
||||
*
|
||||
*/
|
||||
|
||||
;(function(l) {
|
||||
|
||||
var redirectPath;
|
||||
${JSON.stringify(paths)}.forEach(function (path) {
|
||||
if (l.pathname.indexOf(path) === 0) {
|
||||
redirectPath = path;
|
||||
}
|
||||
});
|
||||
|
||||
if (!redirectPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* redirect all 404 traffic to index.html */
|
||||
function redirect() {
|
||||
l.replace(l.protocol + '//' + l.hostname + (l.port ? ':' + l.port : '') + redirectPath + '/?' +
|
||||
(l.pathname ? 'p=' + l.pathname.replace(/&/g, '~and~').replace(redirectPath, '') : '') +
|
||||
(l.search ? '&q=' + l.search.slice(1).replace(/&/g, '~and~') : '') +
|
||||
(l.hash))
|
||||
}
|
||||
|
||||
/* resolve 404 redirects into internal routes */
|
||||
function resolve() {
|
||||
if (l.search) {
|
||||
var q = {};
|
||||
l.search.slice(1).split('&').forEach(function(v) {
|
||||
var a = v.split('=');
|
||||
q[a[0]] = a.slice(1).join('=').replace(/~and~/g, '&')
|
||||
});
|
||||
if (q.p !== undefined) {
|
||||
window.history.replaceState(null, null,
|
||||
redirectPath + (q.p || '') +
|
||||
(q.q ? ('?' + q.q) : '') +
|
||||
l.hash
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if current document is 404 page page, redirect to index.html otherwise resolve */
|
||||
document.title === '404' ? redirect() : resolve()
|
||||
|
||||
}(window.location));
|
||||
`;
|
||||
}
|
||||
3
scripts/docs/log.ts
Normal file
3
scripts/docs/log.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export function log(message: string) {
|
||||
console.log(message);
|
||||
}
|
||||
37
scripts/docs/run-command.ts
Normal file
37
scripts/docs/run-command.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import { exec } from 'child_process';
|
||||
import { promisify } from 'util';
|
||||
|
||||
export interface RunCommandOptions {
|
||||
cwd?: string;
|
||||
showLog?: boolean;
|
||||
}
|
||||
|
||||
const DEFAULT_OPTIONS: RunCommandOptions = { cwd: process.cwd(), showLog: false };
|
||||
|
||||
export async function runCommand(command: string, options?: RunCommandOptions) {
|
||||
let { cwd, showLog } = Object.assign({}, DEFAULT_OPTIONS, options);
|
||||
|
||||
try {
|
||||
console.log(`Running "${command}" in "${cwd}"`);
|
||||
const { stdout, stderr } = await promisify(exec)(command, { cwd });
|
||||
|
||||
if (showLog && stdout) {
|
||||
console.log(stdout);
|
||||
}
|
||||
|
||||
if (stderr) {
|
||||
console.log(`stderr from "${command}" in "${cwd}"`);
|
||||
console.warn(stderr);
|
||||
}
|
||||
} catch ({ message, stdout, stderr }) {
|
||||
let errorMessage = `Error running "${command}" in "${cwd}": ${message}.`;
|
||||
if (stdout) {
|
||||
errorMessage += `\nstdout: ${stdout}`;
|
||||
console.error(stdout);
|
||||
}
|
||||
if (stderr) {
|
||||
errorMessage += `\nstderr: ${stderr}`;
|
||||
}
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
}
|
||||
12
scripts/docs/tsconfig.json
Normal file
12
scripts/docs/tsconfig.json
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"rootDir": ".",
|
||||
"module": "commonjs",
|
||||
"lib": ["es2018"],
|
||||
"target": "es2018",
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": [
|
||||
"build-docs.ts"
|
||||
]
|
||||
}
|
||||
5
scripts/docs/tslint.json
Normal file
5
scripts/docs/tslint.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"rules": {
|
||||
"no-console": false
|
||||
}
|
||||
}
|
||||
8
scripts/publish.sh
Normal file
8
scripts/publish.sh
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Iterates over all modules bundled in the src/.lib and publish them
|
||||
for dir in ./src/.lib/*/
|
||||
do
|
||||
dir=${dir%*/}
|
||||
npm publish --access=public src/.lib/${dir##*/}
|
||||
done
|
||||
Loading…
Add table
Add a link
Reference in a new issue