Skip to content
This repository has been archived by the owner on Jul 4, 2023. It is now read-only.

Commit

Permalink
feat: implement *.pcci.ts / *.js.ts bundling #40
Browse files Browse the repository at this point in the history
  • Loading branch information
shah committed Dec 1, 2021
1 parent fd0ed3c commit 2c81e4d
Show file tree
Hide file tree
Showing 4 changed files with 239 additions and 6 deletions.
54 changes: 48 additions & 6 deletions core/originate/typical-file-sys-globs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as r from "../std/resource.ts";
import * as route from "../std/route.ts";
import * as fm from "../std/frontmatter.ts";
import * as md from "../resource/markdown.ts";
import * as b from "../resource/module/bundle.ts";
import * as html from "../resource/html.ts";
import * as module from "../resource/module/module.ts";
import * as jsonM from "../resource/module/json.ts";
Expand Down Expand Up @@ -128,6 +129,39 @@ export function jsonModuleFileSysGlob(
};
}

export function jsBundleFileSysGlob(
routeParser = route.humanFriendlyFileSysRouteParser,
stage?: string,
): fsg.FileSysPathGlob<b.BundleResource> {
return {
glob: stage ? `**/*.js${stage}.ts` : "**/*.js.ts",
routeParser,
factory: b.bundleFileSysResourceFactory(true),
};
}

export function pciiServerOnlyBundleFileSysGlob(
routeParser = route.humanFriendlyFileSysRouteParser,
stage?: string,
): fsg.FileSysPathGlob<b.BundleResource> {
return {
glob: stage ? `**/*.pcii${stage}.ts` : "**/*.pcii.ts",
routeParser,
factory: b.bundleFileSysResourceFactory(false),
};
}

export function pciiClientAndServerBundleFileSysGlob(
routeParser = route.humanFriendlyFileSysRouteParser,
stage?: string,
): fsg.FileSysPathGlob<b.BundleResource> {
return {
glob: stage ? `**/*.client.pcii${stage}.ts` : "**/*.client.pcii.ts",
routeParser,
factory: b.bundleFileSysResourceFactory(true),
};
}

export function moduleFileSysGlobs<State>(
originRootPath: fsg.FileSysPathText,
fsRouteFactory: route.FileSysRouteFactory,
Expand All @@ -147,20 +181,28 @@ export function moduleFileSysGlobs<State>(
state,
routeParser,
stage,
) as fsg.FileSysPathGlob<
// deno-lint-ignore no-explicit-any
any
>,
) as fsg.FileSysPathGlob<any>,
// deno-lint-ignore no-explicit-any
jsonModuleFileSysGlob(routeParser, stage) as fsg.FileSysPathGlob<any>,
markdownModuleFileSysGlob(
mdrs,
routeParser,
stage,
) as fsg.FileSysPathGlob<
// deno-lint-ignore no-explicit-any
any
>,
) as fsg.FileSysPathGlob<any>,
// deno-lint-ignore no-explicit-any
jsBundleFileSysGlob(routeParser, stage) as fsg.FileSysPathGlob<any>,
pciiServerOnlyBundleFileSysGlob(
routeParser,
stage,
// deno-lint-ignore no-explicit-any
) as fsg.FileSysPathGlob<any>,
pciiClientAndServerBundleFileSysGlob(
routeParser,
stage,
// deno-lint-ignore no-explicit-any
) as fsg.FileSysPathGlob<any>,
],
fileSysGitPaths: g.discoverGitWorkTree(originRootPath),
}],
Expand Down
36 changes: 36 additions & 0 deletions core/render/bundle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { fs } from "../deps.ts";
import * as govn from "../../governance/mod.ts";
import * as br from "../../core/resource/module/bundle.ts";
import * as p from "../../core/std/persist.ts";

export function bundleProducer<State>(
destRootPath: string,
state: State,
options?: {
readonly namingStrategy?: p.LocalFileSystemNamingStrategy<
govn.RouteSupplier<govn.RouteNode>
>;
readonly eventsEmitter?: govn.FileSysPersistEventsEmitterSupplier;
},
// deno-lint-ignore no-explicit-any
): govn.ResourceRefinery<any> {
const namingStrategy = options?.namingStrategy ||
p.routePersistForceExtnNamingStrategy(".js");
return async (resource) => {
if (br.isBundleResource(resource)) {
await p.persistFlexibleFileCustom(
resource,
namingStrategy(
resource as unknown as govn.RouteSupplier<govn.RouteNode>,
destRootPath,
),
{
ensureDirSync: fs.ensureDirSync,
functionArgs: [state],
eventsEmitter: options?.eventsEmitter,
},
);
}
return resource;
};
}
147 changes: 147 additions & 0 deletions core/resource/module/bundle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import { fs } from "../../deps.ts";
import * as govn from "../../../governance/mod.ts";
import * as c from "../../../core/std/content.ts";
import * as fsrf from "../../originate/file-sys-globs.ts";
import * as route from "../../../core/std/route.ts";
import * as nature from "../../../core/std/nature.ts";
import * as p from "../../../core/std/persist.ts";
import * as safety from "../../../lib/safety/mod.ts";

export interface FileSysResourceBundleConstructor<State> {
(
we: fsrf.FileSysGlobWalkEntry<BundleResource>,
options: route.FileSysRouteOptions,
imported: govn.ExtensionModule,
state: State,
): Promise<BundleResource>;
}

export interface BundleResource
extends
govn.TextSupplier,
govn.TextSyncSupplier,
govn.NatureSupplier<
& govn.MediaTypeNature<govn.TextSupplier & govn.TextSyncSupplier>
& govn.FileSysPersistenceSupplier<BundleResource>
>,
govn.RouteSupplier,
Partial<govn.FrontmatterSupplier<govn.UntypedFrontmatter>>,
Partial<govn.DiagnosticsSupplier> {
readonly isClientJavascriptBundle?: boolean;
}

export const isBundleResourceType = safety.typeGuard<BundleResource>(
"nature",
"text",
"textSync",
"isClientJavascriptBundle",
);

export function isBundleResource(o: unknown): o is BundleResource {
if (isBundleResourceType(o)) {
return o.isClientJavascriptBundle ? true : false;
}
return false;
}

export const bundleMediaTypeNature: govn.MediaTypeNature<BundleResource> = {
mediaType: "text/javascript",
guard: (o: unknown): o is BundleResource => {
if (
nature.isNatureSupplier(o) && nature.isMediaTypeNature(o.nature) &&
o.nature.mediaType === bundleMediaTypeNature.mediaType &&
(c.isTextSupplier(o) && c.isTextSyncSupplier(o))
) {
return true;
}
return false;
},
};

export const bundleContentNature:
& govn.MediaTypeNature<govn.TextResource>
& govn.TextSuppliersFactory
& govn.FileSysPersistenceSupplier<BundleResource>
& govn.RenderTargetsSupplier<govn.MediaTypeNature<govn.TextResource>> = {
mediaType: bundleMediaTypeNature.mediaType,
guard: bundleMediaTypeNature.guard,
prepareText: nature.prepareText,
renderTargets: [bundleMediaTypeNature],
persistFileSysRefinery: (rootPath, namingStrategy, eventsEmitter) => {
return async (resource) => {
if (c.isTextSupplier(resource)) {
await p.persistFlexibleFileCustom(
resource,
namingStrategy(resource, rootPath),
{ ensureDirSync: fs.ensureDirSync, eventsEmitter },
);
}
return resource;
};
},
persistFileSys: async (
resource,
rootPath,
namingStrategy,
eventsEmitter,
) => {
if (c.isTextSupplier(resource)) {
await p.persistFlexibleFileCustom(
resource,
namingStrategy(resource, rootPath),
{ ensureDirSync: fs.ensureDirSync, eventsEmitter },
);
}
},
};

export function bundleFileSysResourceFactory(
isClientJavascriptBundle: boolean,
refine?: govn.ResourceRefinery<BundleResource>,
): fsrf.FileSysGlobWalkEntryFactory<BundleResource> {
return {
construct: async (origination, options) => {
// doing this will make PCII available at the server side
const imported = await options.extensionsManager.importModule(
origination.path,
);
let content = "// bundler did not run?";
if (imported.isValid) {
try {
const { files, diagnostics } = await Deno.emit(origination.path, {
bundle: "classic",
compilerOptions: {
lib: ["deno.unstable", "deno.window"],
},
});
if (diagnostics.length) {
content = Deno.formatDiagnostics(diagnostics);
} else {
content = files["deno:///bundle.js"];
}
} catch (e) {
content = `// Error emitting ${origination.path}: ${e}`;
}
} else {
content =
`// Invalid Module ${origination.path}: ${imported.importError}`;
}
const nature = bundleContentNature;
const result:
& BundleResource
& govn.RouteSupplier = {
isClientJavascriptBundle,
nature,
route: {
...origination.route,
nature,
},
// deno-lint-ignore require-await
text: async () => content,
textSync: () => content,
};
return result;
},
refine,
};
}
8 changes: 8 additions & 0 deletions executive/publ/publication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import * as tfsg from "../../core/originate/typical-file-sys-globs.ts";
import * as html from "../../core/render/html/mod.ts";
import * as jrs from "../../core/render/json.ts";
import * as tfr from "../../core/render/text.ts";
import * as br from "../../core/render/bundle.ts";
import * as dtr from "../../core/render/delimited-text.ts";
import * as mdr from "../../core/render/markdown/mod.ts";

Expand Down Expand Up @@ -680,6 +681,13 @@ export abstract class TypicalPublication<OCState>
eventsEmitter: ees,
},
),
br.bundleProducer<PublicationState>(
this.config.destRootPath,
this.state,
{
eventsEmitter: ees,
},
),
);
}

Expand Down

0 comments on commit 2c81e4d

Please sign in to comment.