create-astrale-domain 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +117 -28
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -789,23 +789,25 @@ var require2 = createRequire(import.meta.url);
|
|
|
789
789
|
var HERE = dirname(fileURLToPath(import.meta.url));
|
|
790
790
|
var WORKSPACE_ROOT = join(HERE, "..", "..", "..");
|
|
791
791
|
var ORIGIN_PLACEHOLDER = "astrale-domain.example.dev";
|
|
792
|
+
var INSTANCE_PLACEHOLDER = "my-instance-slug";
|
|
792
793
|
var LINK_TARGETS = {
|
|
793
794
|
"@astrale-os/sdk": "sdk",
|
|
794
|
-
"@astrale-os/devkit": "sdk/devkit",
|
|
795
795
|
"@astrale-os/adapter-cloudflare": "sdk/adapter-cloudflare",
|
|
796
|
+
"@astrale-os/adapter-astrale": "sdk/adapter-astrale",
|
|
796
797
|
"@astrale-os/kernel-core": "kernel/core",
|
|
797
798
|
"@astrale-os/kernel-dsl": "kernel/dsl"
|
|
798
799
|
};
|
|
800
|
+
var BODY_PACKAGE = "@astrale-os/adapter-cloudflare";
|
|
799
801
|
var ADAPTER_PACKAGES = {
|
|
802
|
+
astrale: "@astrale-os/adapter-astrale",
|
|
800
803
|
cloudflare: "@astrale-os/adapter-cloudflare"
|
|
801
804
|
};
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
if (!pkg) throw new Error(`No template package registered for adapter "${adapter}".`);
|
|
805
|
+
var ADAPTER_DEP_RANGE = ">=0.1.0 <1.0.0";
|
|
806
|
+
function templateDir(pkg) {
|
|
805
807
|
return join(dirname(require2.resolve(`${pkg}/package.json`)), "template");
|
|
806
808
|
}
|
|
807
809
|
async function scaffold(opts) {
|
|
808
|
-
const src = templateDir(
|
|
810
|
+
const src = templateDir(BODY_PACKAGE);
|
|
809
811
|
if (!existsSync(src)) {
|
|
810
812
|
throw new Error(`Template not found at ${src}.`);
|
|
811
813
|
}
|
|
@@ -817,6 +819,7 @@ async function scaffold(opts) {
|
|
|
817
819
|
recursive: true,
|
|
818
820
|
filter: (s) => !/\/(node_modules|\.astrale|dist-client|\.wrangler)(\/|$)/.test(`/${relative(src, s)}`)
|
|
819
821
|
});
|
|
822
|
+
await materializeAdapter(opts);
|
|
820
823
|
await stampOrigin(opts.dir, opts.origin);
|
|
821
824
|
await rewritePackageJson(opts.dir, opts.name, opts.link);
|
|
822
825
|
await writeFile(
|
|
@@ -840,6 +843,24 @@ async function stampOrigin(dir, origin) {
|
|
|
840
843
|
const config = join(dir, "astrale.config.ts");
|
|
841
844
|
await replaceInFile(config, ORIGIN_PLACEHOLDER, origin);
|
|
842
845
|
}
|
|
846
|
+
async function materializeAdapter(opts) {
|
|
847
|
+
if (opts.adapter !== "astrale") return;
|
|
848
|
+
const config = join(opts.dir, "astrale.config.ts");
|
|
849
|
+
await cp(join(templateDir(ADAPTER_PACKAGES.astrale), "astrale.config.ts"), config);
|
|
850
|
+
await setAdapterDep(opts.dir, "@astrale-os/adapter-cloudflare", "@astrale-os/adapter-astrale");
|
|
851
|
+
if (opts.instance) await replaceInFile(config, `'${INSTANCE_PLACEHOLDER}'`, `'${opts.instance}'`);
|
|
852
|
+
}
|
|
853
|
+
async function setAdapterDep(dir, from, to) {
|
|
854
|
+
const path = join(dir, "package.json");
|
|
855
|
+
const pkg = JSON.parse(await readFile(path, "utf-8"));
|
|
856
|
+
if (!pkg.dependencies || !(from in pkg.dependencies)) return;
|
|
857
|
+
delete pkg.dependencies[from];
|
|
858
|
+
pkg.dependencies[to] = ADAPTER_DEP_RANGE;
|
|
859
|
+
pkg.dependencies = Object.fromEntries(
|
|
860
|
+
Object.entries(pkg.dependencies).sort(([a], [b3]) => a.localeCompare(b3))
|
|
861
|
+
);
|
|
862
|
+
await writeFile(path, JSON.stringify(pkg, null, 2) + "\n");
|
|
863
|
+
}
|
|
843
864
|
async function rewritePackageJson(dir, name, link) {
|
|
844
865
|
const path = join(dir, "package.json");
|
|
845
866
|
const pkg = JSON.parse(await readFile(path, "utf-8"));
|
|
@@ -877,18 +898,53 @@ export {}
|
|
|
877
898
|
`import { defineSchema, KernelSchema } from '@astrale-os/kernel-core'
|
|
878
899
|
|
|
879
900
|
export const schema = defineSchema('${origin}', {
|
|
901
|
+
interfaces: {},
|
|
902
|
+
classes: {},
|
|
880
903
|
imports: [KernelSchema],
|
|
881
904
|
})
|
|
882
905
|
`
|
|
883
906
|
);
|
|
884
907
|
await writeFile(
|
|
885
|
-
join(dir, "
|
|
908
|
+
join(dir, "env.ts"),
|
|
909
|
+
`/**
|
|
910
|
+
* Worker runtime env. The adapter injects \`WORKER_URL\` and the bindings; your
|
|
911
|
+
* handlers receive this (mapped by deps.ts) as \`ctx.deps\`. Secrets from
|
|
912
|
+
* \`.env.<env>\` arrive as extra string fields here. Add typed fields as you
|
|
913
|
+
* reference new secrets/vars.
|
|
914
|
+
*/
|
|
915
|
+
export interface Env {
|
|
916
|
+
WORKER_URL?: string
|
|
917
|
+
ASSETS?: { fetch(request: Request): Promise<Response> }
|
|
918
|
+
SELF?: { fetch(request: Request): Promise<Response> }
|
|
919
|
+
VIEW_DEV_URL?: string
|
|
920
|
+
[key: string]: unknown
|
|
921
|
+
}
|
|
922
|
+
`
|
|
923
|
+
);
|
|
924
|
+
await writeFile(
|
|
925
|
+
join(dir, "deps.ts"),
|
|
926
|
+
`/**
|
|
927
|
+
* env \u2192 handler dependency container (the seam \`defineDomain({ deps })\` mounts).
|
|
928
|
+
* Passthrough by default; transform here the moment a handler should depend on a
|
|
929
|
+
* PORT (built from \`integrations/\`) instead of raw env.
|
|
930
|
+
*/
|
|
931
|
+
import type { Env } from './env'
|
|
932
|
+
|
|
933
|
+
export interface Deps extends Env {}
|
|
934
|
+
|
|
935
|
+
export function deps(env: Env): Deps {
|
|
936
|
+
return env
|
|
937
|
+
}
|
|
938
|
+
`
|
|
939
|
+
);
|
|
940
|
+
await writeFile(
|
|
941
|
+
join(dir, "runtime", "index.ts"),
|
|
886
942
|
`import type { SchemaMethodsImpl } from '@astrale-os/sdk'
|
|
887
943
|
|
|
888
|
-
import type {
|
|
944
|
+
import type { Deps } from '../deps'
|
|
889
945
|
import { schema } from '../schema'
|
|
890
946
|
|
|
891
|
-
export const methods: SchemaMethodsImpl<typeof schema,
|
|
947
|
+
export const methods: SchemaMethodsImpl<typeof schema, Deps> = { class: {} }
|
|
892
948
|
`
|
|
893
949
|
);
|
|
894
950
|
await writeFile(join(dir, "functions", "index.ts"), `export const functions = {}
|
|
@@ -896,12 +952,12 @@ export const methods: SchemaMethodsImpl<typeof schema, Env> = {}
|
|
|
896
952
|
await writeFile(join(dir, "views", "index.ts"), `export const views = {}
|
|
897
953
|
`);
|
|
898
954
|
await rm(join(dir, "schema", "compiled.ts"), { force: true });
|
|
899
|
-
await rm(join(dir, "
|
|
900
|
-
await rm(join(dir, "
|
|
955
|
+
await rm(join(dir, "core"), { recursive: true, force: true });
|
|
956
|
+
await rm(join(dir, "integrations"), { recursive: true, force: true });
|
|
901
957
|
await rm(join(dir, "views", "welcome.ts"), { force: true });
|
|
902
958
|
await rm(join(dir, "views", "note.ts"), { force: true });
|
|
903
959
|
await replaceInFile(
|
|
904
|
-
join(dir, "
|
|
960
|
+
join(dir, "domain.ts"),
|
|
905
961
|
/\n\s*postInstall: `\/:\$\{schema\.domain\}:class\.Note:seed`,/,
|
|
906
962
|
""
|
|
907
963
|
);
|
|
@@ -913,7 +969,7 @@ async function replaceInFile(path, from, to) {
|
|
|
913
969
|
if (next !== text) await writeFile(path, next);
|
|
914
970
|
}
|
|
915
971
|
function workspaceAvailable() {
|
|
916
|
-
return existsSync(join(WORKSPACE_ROOT, "sdk", "
|
|
972
|
+
return existsSync(join(WORKSPACE_ROOT, "sdk", "package.json"));
|
|
917
973
|
}
|
|
918
974
|
|
|
919
975
|
// src/index.ts
|
|
@@ -926,15 +982,15 @@ var DLX = {
|
|
|
926
982
|
};
|
|
927
983
|
var ADAPTERS = [
|
|
928
984
|
{
|
|
929
|
-
value: "astrale
|
|
930
|
-
label: "Astrale
|
|
931
|
-
hint: "
|
|
932
|
-
enabled:
|
|
985
|
+
value: "astrale",
|
|
986
|
+
label: "Astrale managed",
|
|
987
|
+
hint: "publishes through the platform onto your instance \u2014 no Cloudflare account",
|
|
988
|
+
enabled: true
|
|
933
989
|
},
|
|
934
990
|
{
|
|
935
991
|
value: "cloudflare",
|
|
936
992
|
label: "Cloudflare Worker",
|
|
937
|
-
hint: "
|
|
993
|
+
hint: "your own CF account (*.workers.dev / custom domain)",
|
|
938
994
|
enabled: true
|
|
939
995
|
},
|
|
940
996
|
{ value: "custom", label: "Custom", hint: "bring your own adapter (soon)", enabled: false }
|
|
@@ -968,11 +1024,11 @@ async function main() {
|
|
|
968
1024
|
}
|
|
969
1025
|
let adapter = flags.adapter;
|
|
970
1026
|
if (!adapter) {
|
|
971
|
-
if (headless) adapter = "
|
|
1027
|
+
if (headless) adapter = "astrale";
|
|
972
1028
|
else {
|
|
973
1029
|
const answer = await ve({
|
|
974
1030
|
message: "Where will it run? (deployment adapter)",
|
|
975
|
-
initialValue: "
|
|
1031
|
+
initialValue: "astrale",
|
|
976
1032
|
options: ADAPTERS.map((a) => ({
|
|
977
1033
|
value: a.value,
|
|
978
1034
|
label: a.enabled ? a.label : `${a.label} (soon)`,
|
|
@@ -983,10 +1039,24 @@ async function main() {
|
|
|
983
1039
|
adapter = answer;
|
|
984
1040
|
}
|
|
985
1041
|
}
|
|
986
|
-
if (adapter !== "cloudflare") {
|
|
987
|
-
xe(`The "${adapter}" adapter is not available yet \u2014
|
|
1042
|
+
if (adapter !== "astrale" && adapter !== "cloudflare") {
|
|
1043
|
+
xe(`The "${adapter}" adapter is not available yet \u2014 use "astrale" or "cloudflare".`);
|
|
988
1044
|
return 1;
|
|
989
1045
|
}
|
|
1046
|
+
let instance = flags.instance;
|
|
1047
|
+
if (instance !== void 0 && !isValidSlug(instance)) {
|
|
1048
|
+
xe(`Invalid --instance "${instance}". Use lowercase letters, digits, dots and dashes.`);
|
|
1049
|
+
return 1;
|
|
1050
|
+
}
|
|
1051
|
+
if (adapter === "astrale" && !instance && !headless) {
|
|
1052
|
+
const answer = await he({
|
|
1053
|
+
message: "Target instance slug (`astrale instance create <slug>` \u2014 empty to set it later)",
|
|
1054
|
+
placeholder: "my-app",
|
|
1055
|
+
validate: (v2) => !v2 || isValidSlug(v2) ? void 0 : "Use lowercase letters, digits, dots and dashes."
|
|
1056
|
+
});
|
|
1057
|
+
if (pD(answer)) return bail();
|
|
1058
|
+
if (answer) instance = answer;
|
|
1059
|
+
}
|
|
990
1060
|
let template = flags.template;
|
|
991
1061
|
if (!template) {
|
|
992
1062
|
if (headless) template = "template";
|
|
@@ -1043,8 +1113,9 @@ async function main() {
|
|
|
1043
1113
|
dir,
|
|
1044
1114
|
name: slug,
|
|
1045
1115
|
origin,
|
|
1046
|
-
adapter
|
|
1116
|
+
adapter,
|
|
1047
1117
|
template,
|
|
1118
|
+
instance,
|
|
1048
1119
|
link
|
|
1049
1120
|
});
|
|
1050
1121
|
s.stop(`Created ${dir}`);
|
|
@@ -1059,22 +1130,38 @@ async function main() {
|
|
|
1059
1130
|
const rel = relative2(process.cwd(), dir);
|
|
1060
1131
|
const cdTarget = rel && !rel.startsWith("..") ? rel : dir;
|
|
1061
1132
|
Me(
|
|
1062
|
-
[
|
|
1133
|
+
[
|
|
1134
|
+
`cd ${cdTarget}`,
|
|
1135
|
+
`${pm} install`,
|
|
1136
|
+
devStep(pm),
|
|
1137
|
+
installStep(pm),
|
|
1138
|
+
prodStep(pm, adapter, instance)
|
|
1139
|
+
].join("\n"),
|
|
1063
1140
|
"Next"
|
|
1064
1141
|
);
|
|
1142
|
+
if (adapter === "astrale" && !instance) {
|
|
1143
|
+
M2.warn(
|
|
1144
|
+
`No target instance set \u2014 put your slug in astrale.config.ts (prod.instance) before \`${pm === "npm" ? "npm run prod" : `${pm} prod`}\`. Create one: astrale instance create <slug>`
|
|
1145
|
+
);
|
|
1146
|
+
}
|
|
1065
1147
|
M2.info(
|
|
1066
|
-
|
|
1148
|
+
`AI agent on this project? The full authoring guide ships at .agents/skills/astrale-domain/SKILL.md
|
|
1149
|
+
Agent rooted at a parent workspace? Register the skills there: npx skills add ${cdTarget === dir ? dir : `./${cdTarget}`}/.agents/skills -y`
|
|
1067
1150
|
);
|
|
1068
1151
|
Se(`\u2713 ${slug} ready`);
|
|
1069
1152
|
return 0;
|
|
1070
1153
|
}
|
|
1071
1154
|
var devStep = (pm) => `${pm === "npm" ? "npm run dev" : `${pm} dev`} # wrangler dev \u2192 prints a local URL`;
|
|
1072
|
-
var prodStep = (pm) =>
|
|
1155
|
+
var prodStep = (pm, adapter, instance) => {
|
|
1156
|
+
const cmd = pm === "npm" ? "npm run prod" : `${pm} prod`;
|
|
1157
|
+
const hint = adapter === "astrale" ? `# managed deploy \u2192 installs on ${instance ? `"${instance}"` : "your instance"}` : "# deploy prod \u2192 prints a URL";
|
|
1158
|
+
return `${cmd} ${hint}`;
|
|
1159
|
+
};
|
|
1073
1160
|
function installStep(pm) {
|
|
1074
|
-
if (astraleOnPath()) return "astrale
|
|
1161
|
+
if (astraleOnPath()) return "astrale domain install <url> --direct # mount it on an instance";
|
|
1075
1162
|
return [
|
|
1076
1163
|
"# astrale CLI not found on PATH \u2014 run it on demand (no install):",
|
|
1077
|
-
`${DLX[pm]} @astrale-os/astrale
|
|
1164
|
+
`${DLX[pm]} @astrale-os/astrale domain install <url> --direct`,
|
|
1078
1165
|
"# or install it globally: npm i -g @astrale-os/astrale"
|
|
1079
1166
|
].join("\n");
|
|
1080
1167
|
}
|
|
@@ -1102,6 +1189,7 @@ function parseFlags(argv) {
|
|
|
1102
1189
|
else if (a === "--pm") flags.pm = argv[++i];
|
|
1103
1190
|
else if (a === "--dir") flags.dir = argv[++i];
|
|
1104
1191
|
else if (a === "--origin") flags.origin = argv[++i];
|
|
1192
|
+
else if (a === "--instance") flags.instance = argv[++i];
|
|
1105
1193
|
else if (!a.startsWith("-")) flags.positional.push(a);
|
|
1106
1194
|
}
|
|
1107
1195
|
return flags;
|
|
@@ -1119,7 +1207,8 @@ Arguments:
|
|
|
1119
1207
|
<slug> domain name (lowercase letters, digits, dots, dashes)
|
|
1120
1208
|
|
|
1121
1209
|
Options:
|
|
1122
|
-
--adapter <id> deployment adapter \u2014
|
|
1210
|
+
--adapter <id> deployment adapter \u2014 astrale (managed, default) | cloudflare
|
|
1211
|
+
--instance <slug> target instance for managed deploys (astrale adapter)
|
|
1123
1212
|
--template <kind> template | blank (default: template)
|
|
1124
1213
|
--pm <pm> pnpm | npm | yarn | bun (default: detected, else pnpm)
|
|
1125
1214
|
--dir <path> target directory (default: ./<slug>)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-astrale-domain",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Scaffold a standalone Astrale domain — npm create astrale-domain",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astrale",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"type": "module",
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@clack/prompts": "^0.11.0",
|
|
22
|
-
"@astrale-os/adapter-cloudflare": "^0.1.
|
|
22
|
+
"@astrale-os/adapter-cloudflare": "^0.1.9",
|
|
23
|
+
"@astrale-os/adapter-astrale": "^0.1.0"
|
|
23
24
|
},
|
|
24
25
|
"devDependencies": {
|
|
25
26
|
"@astrale-os/ox": ">=0.1.0 <1.0.0",
|