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.
Files changed (2) hide show
  1. package/dist/index.js +117 -28
  2. 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
- function templateDir(adapter) {
803
- const pkg = ADAPTER_PACKAGES[adapter];
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(opts.adapter);
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, "methods", "index.ts"),
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 { Env } from '../env'
944
+ import type { Deps } from '../deps'
889
945
  import { schema } from '../schema'
890
946
 
891
- export const methods: SchemaMethodsImpl<typeof schema, Env> = {}
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, "methods", "note.ts"), { force: true });
900
- await rm(join(dir, "functions", "seed.ts"), { force: true });
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, "astrale.config.ts"),
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", "devkit", "package.json"));
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-host",
930
- label: "Astrale Worker",
931
- hint: "deployed under /service on an Astrale host (soon)",
932
- enabled: false
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: "standalone worker (*.workers.dev / custom domain)",
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 = "cloudflare";
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: "cloudflare",
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 only "cloudflare" is wired today.`);
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: "cloudflare",
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
- [`cd ${cdTarget}`, `${pm} install`, devStep(pm), installStep(pm), prodStep(pm)].join("\n"),
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
- "AI agent on this project? The full authoring guide ships at .agents/skills/astrale-domain/SKILL.md"
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) => `${pm === "npm" ? "npm run prod" : `${pm} prod`} # deploy prod \u2192 prints a URL`;
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 instance install <url> # mount it on an instance";
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 instance install <url>`,
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 cloudflare (default; others soon)
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.4",
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.7"
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",