create-eigen-game 0.12.1 → 0.13.0
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/cli.d.ts +1 -0
- package/dist/engine-range.d.ts +39 -0
- package/dist/index.d.ts +23 -31
- package/dist/link-firebase.d.ts +28 -0
- package/dist/prompt.d.ts +79 -0
- package/dist/summary.d.ts +26 -0
- package/package.json +6 -6
- package/templates/worker/package.json +1 -1
package/dist/cli.d.ts
CHANGED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where the engine range emitted into a scaffolded project comes from.
|
|
3
|
+
*
|
|
4
|
+
* Its own module because the two branches below execute in different worlds,
|
|
5
|
+
* one only inside this repository and the other only inside a published tarball,
|
|
6
|
+
* and a function whose published-only path never runs in CI is a function that
|
|
7
|
+
* is not tested. `src/index.ts` uses it; the package `exports` map does not
|
|
8
|
+
* expose it, so it is internal despite being importable by the tests.
|
|
9
|
+
*/
|
|
10
|
+
/** The dependency whose version the scaffolder emits into the generated server. */
|
|
11
|
+
export declare const ENGINE_PACKAGE = "@eigeninteractive/server";
|
|
12
|
+
/**
|
|
13
|
+
* The engine range for a scaffolded project, from this package's own
|
|
14
|
+
* `@eigeninteractive/server` devDependency.
|
|
15
|
+
*
|
|
16
|
+
* That number is not maintained by anyone: it is the version CI compiled the
|
|
17
|
+
* templates against, because `pnpm -r typecheck` runs
|
|
18
|
+
* `tsc -p templates/worker/tsconfig.json` inside this workspace. Emitting
|
|
19
|
+
* anything else would mean shipping templates paired with an engine no build
|
|
20
|
+
* ever saw.
|
|
21
|
+
*
|
|
22
|
+
* It replaced a derivation from this package's OWN version, which was correct
|
|
23
|
+
* only while `create-eigen-game` sat in the `fixed` changesets group, and that
|
|
24
|
+
* membership is what forced an engine-wide release for every scaffolder-only
|
|
25
|
+
* change. Reading the dependency keeps the guarantee and drops the coupling.
|
|
26
|
+
*
|
|
27
|
+
* Two branches, because the same manifest reads differently in the two places
|
|
28
|
+
* this runs:
|
|
29
|
+
*
|
|
30
|
+
* - **Published tarball**: pnpm rewrites `workspace:*` to the exact version
|
|
31
|
+
* while packing, so the manifest already states it (`"0.2.0"`), and no
|
|
32
|
+
* sibling package exists on disk to consult.
|
|
33
|
+
* - **This workspace**: the manifest still says `workspace:*`, which names no
|
|
34
|
+
* version, so the sibling package is read directly.
|
|
35
|
+
*
|
|
36
|
+
* @param declared the raw `@eigeninteractive/server` devDependency value
|
|
37
|
+
* @param readSiblingVersion consulted only for the `workspace:` protocol
|
|
38
|
+
*/
|
|
39
|
+
export declare function engineRange(declared: string | undefined, readSiblingVersion: () => string | undefined): string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
/** The OAuth web client now in `app-config.json`, or null when Google sign-in is not enabled yet. */
|
|
6
|
-
googleWebClientId: string | null;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
type PackageManager = "npm" | "pnpm";
|
|
10
|
-
type Runner = (command: string, args: string[], cwd: string) => void;
|
|
1
|
+
import { type FirebaseLink } from "./link-firebase.js";
|
|
2
|
+
export type { FirebaseLink } from "./link-firebase.js";
|
|
3
|
+
export type PackageManager = "npm" | "pnpm";
|
|
4
|
+
export type Runner = (command: string, args: string[], cwd: string) => void;
|
|
11
5
|
/**
|
|
12
6
|
* Where a scaffold says what it is doing, so that presentation belongs to the
|
|
13
7
|
* caller and this module only has to name things.
|
|
@@ -17,7 +11,7 @@ type Runner = (command: string, args: string[], cwd: string) => void;
|
|
|
17
11
|
* substitutes one that captures each step's output and shows it only if the
|
|
18
12
|
* step fails.
|
|
19
13
|
*/
|
|
20
|
-
interface Reporter {
|
|
14
|
+
export interface Reporter {
|
|
21
15
|
/** Runs `body` as one named step. Its subprocesses can be captured. */
|
|
22
16
|
step<T>(label: string, body: () => T): T;
|
|
23
17
|
/**
|
|
@@ -42,12 +36,12 @@ interface Reporter {
|
|
|
42
36
|
* with `RangeError: Invalid string length`. Supplying the default its check
|
|
43
37
|
* misses is better than giving up the drawing.
|
|
44
38
|
*/
|
|
45
|
-
declare function normaliseTerminalWidth(stream: {
|
|
39
|
+
export declare function normaliseTerminalWidth(stream: {
|
|
46
40
|
isTTY?: boolean;
|
|
47
41
|
columns?: number;
|
|
48
42
|
}): void;
|
|
49
43
|
/** Runs every step plainly, which is what a library caller gets by default. */
|
|
50
|
-
declare const plainReporter: Reporter;
|
|
44
|
+
export declare const plainReporter: Reporter;
|
|
51
45
|
/**
|
|
52
46
|
* The runner a scaffold uses when the caller has not supplied one: it asks the
|
|
53
47
|
* reporter whether the terminal is spoken for.
|
|
@@ -57,8 +51,8 @@ declare const plainReporter: Reporter;
|
|
|
57
51
|
* handed to the reporter: on success so it can discard them, and on failure
|
|
58
52
|
* so the reason survives.
|
|
59
53
|
*/
|
|
60
|
-
declare function capturingRunner(reporter: Reporter): Runner;
|
|
61
|
-
interface ScaffoldOptions {
|
|
54
|
+
export declare function capturingRunner(reporter: Reporter): Runner;
|
|
55
|
+
export interface ScaffoldOptions {
|
|
62
56
|
directory: string;
|
|
63
57
|
org?: string;
|
|
64
58
|
packageManager?: PackageManager;
|
|
@@ -107,8 +101,8 @@ interface ScaffoldOptions {
|
|
|
107
101
|
* than guess. `failed` has already warned by the time it is returned, and
|
|
108
102
|
* carries no advice of its own.
|
|
109
103
|
*/
|
|
110
|
-
type GitOutcome = "committed" | "existing" | "skipped" | "failed";
|
|
111
|
-
interface ScaffoldResult {
|
|
104
|
+
export type GitOutcome = "committed" | "existing" | "skipped" | "failed";
|
|
105
|
+
export interface ScaffoldResult {
|
|
112
106
|
root: string;
|
|
113
107
|
name: string;
|
|
114
108
|
git: GitOutcome;
|
|
@@ -132,10 +126,10 @@ interface ScaffoldResult {
|
|
|
132
126
|
* the *prefix*, not the whole identifier, which is the part worth seeing
|
|
133
127
|
* before answering: Google Play makes it permanent at first upload.
|
|
134
128
|
*/
|
|
135
|
-
declare function applicationId(directory: string, org?: string): string;
|
|
136
|
-
declare function detectPackageManager(userAgent?: string | undefined): PackageManager | undefined;
|
|
137
|
-
declare function decodeUtf8(bytes: Buffer): string | undefined;
|
|
138
|
-
interface AddContinuousIntegrationOptions {
|
|
129
|
+
export declare function applicationId(directory: string, org?: string): string;
|
|
130
|
+
export declare function detectPackageManager(userAgent?: string | undefined): PackageManager | undefined;
|
|
131
|
+
export declare function decodeUtf8(bytes: Buffer): string | undefined;
|
|
132
|
+
export interface AddContinuousIntegrationOptions {
|
|
139
133
|
directory: string;
|
|
140
134
|
/** Overrides the manager recorded in the project's own package.json. */
|
|
141
135
|
packageManager?: PackageManager;
|
|
@@ -147,23 +141,23 @@ interface AddContinuousIntegrationOptions {
|
|
|
147
141
|
* long as its author likes, then gain the same PR gate and signed release
|
|
148
142
|
* pipeline a `--ci` scaffold would have produced.
|
|
149
143
|
*/
|
|
150
|
-
declare function addContinuousIntegration(options: AddContinuousIntegrationOptions): {
|
|
144
|
+
export declare function addContinuousIntegration(options: AddContinuousIntegrationOptions): {
|
|
151
145
|
root: string;
|
|
152
146
|
files: string[];
|
|
153
147
|
};
|
|
154
148
|
/** Asks a command a question. `ok` is "ran and succeeded"; a tool that is not installed and one that fails are both `false`, because neither can be used. */
|
|
155
|
-
type Probe = (command: string, args: string[]) => {
|
|
149
|
+
export type Probe = (command: string, args: string[]) => {
|
|
156
150
|
ok: boolean;
|
|
157
151
|
stdout: string;
|
|
158
152
|
};
|
|
159
153
|
/** One thing standing between this machine and a configured Firebase project, and the single command that clears it. */
|
|
160
|
-
interface FirebaseProblem {
|
|
154
|
+
export interface FirebaseProblem {
|
|
161
155
|
/** Said as a sentence fragment, so it reads after "Firebase is not set up here:". */
|
|
162
156
|
reason: string;
|
|
163
157
|
/** The one command that fixes this, and nothing else. */
|
|
164
158
|
fix: string;
|
|
165
159
|
}
|
|
166
|
-
type FirebaseReadiness = {
|
|
160
|
+
export type FirebaseReadiness = {
|
|
167
161
|
ready: true;
|
|
168
162
|
} | {
|
|
169
163
|
ready: false;
|
|
@@ -189,7 +183,7 @@ type FirebaseReadiness = {
|
|
|
189
183
|
* that errors or grows a different output shape is left to the command that
|
|
190
184
|
* actually needs the credentials.
|
|
191
185
|
*/
|
|
192
|
-
declare function firebaseReadiness(probe?: Probe): FirebaseReadiness;
|
|
186
|
+
export declare function firebaseReadiness(probe?: Probe): FirebaseReadiness;
|
|
193
187
|
/**
|
|
194
188
|
* Whether the scaffold would land inside a repository that already exists.
|
|
195
189
|
*
|
|
@@ -222,8 +216,6 @@ declare function firebaseReadiness(probe?: Probe): FirebaseReadiness;
|
|
|
222
216
|
* the last one. {@link scaffoldGame} asks it again, for callers that are not
|
|
223
217
|
* the CLI.
|
|
224
218
|
*/
|
|
225
|
-
declare function destinationProblem(directory: string): string | undefined;
|
|
226
|
-
declare function insideWorkTree(directory: string, probe?: Probe): boolean;
|
|
227
|
-
declare function scaffoldGame(options: ScaffoldOptions): ScaffoldResult;
|
|
228
|
-
|
|
229
|
-
export { type AddContinuousIntegrationOptions, type FirebaseLink, type FirebaseProblem, type FirebaseReadiness, type GitOutcome, type PackageManager, type Probe, type Reporter, type Runner, type ScaffoldOptions, type ScaffoldResult, addContinuousIntegration, applicationId, capturingRunner, decodeUtf8, destinationProblem, detectPackageManager, firebaseReadiness, insideWorkTree, normaliseTerminalWidth, plainReporter, scaffoldGame };
|
|
219
|
+
export declare function destinationProblem(directory: string): string | undefined;
|
|
220
|
+
export declare function insideWorkTree(directory: string, probe?: Probe): boolean;
|
|
221
|
+
export declare function scaffoldGame(options: ScaffoldOptions): ScaffoldResult;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** What the Firebase step managed to settle, and what it left for the console. */
|
|
2
|
+
export interface FirebaseLink {
|
|
3
|
+
/** The project now in `wrangler.jsonc`, or null when FlutterFire recorded none. */
|
|
4
|
+
projectId: string | null;
|
|
5
|
+
/** The OAuth web client now in `app-config.json`, or null when Google sign-in is not enabled yet. */
|
|
6
|
+
googleWebClientId: string | null;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The project FlutterFire recorded for the Dart output this app uses.
|
|
10
|
+
*
|
|
11
|
+
* `firebase.json` is FlutterFire's own record rather than something this
|
|
12
|
+
* scaffold writes, so it is read defensively: a shape that does not match is
|
|
13
|
+
* treated as "not configured", which is the same answer as a run that never
|
|
14
|
+
* happened.
|
|
15
|
+
*/
|
|
16
|
+
export declare function configuredProject(appRoot: string): string | null;
|
|
17
|
+
/**
|
|
18
|
+
* The OAuth web client id that `configure_firebase` copied into
|
|
19
|
+
* `app-config.json`, when there was one to copy.
|
|
20
|
+
*
|
|
21
|
+
* Empty is an ordinary outcome rather than a failure. Firebase creates that
|
|
22
|
+
* client when the Google sign-in provider is enabled, which is a console
|
|
23
|
+
* action no CLI can perform, so a project that has never had it enabled has
|
|
24
|
+
* nothing to offer here.
|
|
25
|
+
*/
|
|
26
|
+
export declare function configuredWebClientId(appRoot: string): string | null;
|
|
27
|
+
/** What the Firebase step settled, for the summary to report. */
|
|
28
|
+
export declare function readFirebaseLink(root: string): FirebaseLink;
|
package/dist/prompt.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every question this CLI asks, in one module so the wording lives together
|
|
3
|
+
* and can be asserted. `cli.ts` is the bin entry and runs `main` on import,
|
|
4
|
+
* which makes anything defined there untestable.
|
|
5
|
+
*
|
|
6
|
+
* The organization prompt is the reason this drops to `@clack/core` rather
|
|
7
|
+
* than using `@clack/prompts`' `text`. The suffix: `flutter create --org X
|
|
8
|
+
* --project-name Y` derives `X.Y`, so the organization is a *prefix*, and the
|
|
9
|
+
* reliable way to say so is to render the rest of the identifier, dimmed,
|
|
10
|
+
* while it is being typed. `text` has no hook for that; a custom `TextPrompt`
|
|
11
|
+
* render returns a string, so it does.
|
|
12
|
+
*
|
|
13
|
+
* Everything else comes from `@clack/prompts` rather than being drawn here.
|
|
14
|
+
* Its symbols are exported for exactly this, and they are not constants: each
|
|
15
|
+
* falls back to ASCII on a terminal that cannot show the box-drawing
|
|
16
|
+
* characters, which a hand-typed `│` cannot do.
|
|
17
|
+
*/
|
|
18
|
+
import type { Readable, Writable } from "node:stream";
|
|
19
|
+
import type { PackageManager } from "./index.js";
|
|
20
|
+
/**
|
|
21
|
+
* Where a question reads its answer from. Parameters for the same reason every
|
|
22
|
+
* clack prompt takes them: a prompt is otherwise the one part of a CLI that
|
|
23
|
+
* cannot be driven by a test.
|
|
24
|
+
*/
|
|
25
|
+
export interface Io {
|
|
26
|
+
input?: Readable;
|
|
27
|
+
output?: Writable;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Two or more dot-separated Java identifiers. `flutter create --org` accepts
|
|
31
|
+
* anything and defers the complaint to Gradle, which reports it as a manifest
|
|
32
|
+
* error in a generated file, so `com.example-games` costs a full scaffold and
|
|
33
|
+
* a first build before anyone learns that a hyphen is not legal in a package
|
|
34
|
+
* segment.
|
|
35
|
+
*/
|
|
36
|
+
export declare const ORG: RegExp;
|
|
37
|
+
/** The default, which an empty answer accepts. */
|
|
38
|
+
export declare const DEFAULT_ORG = "com.example";
|
|
39
|
+
/** A `com.acme.chess` answer to a game called `chess`, which yields `com.acme.chess.chess`. */
|
|
40
|
+
export declare function repeatsGameName(org: string, game: string): boolean;
|
|
41
|
+
/** The organization implied by an answer that already ends in the game name. */
|
|
42
|
+
export declare function withoutGameName(org: string): string | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Asks, with the game name rendered dimmed after the cursor so the shape of
|
|
45
|
+
* the answer is visible while it is being given.
|
|
46
|
+
*
|
|
47
|
+
* Returns the organization, `undefined` for the default, or `null` when
|
|
48
|
+
* cancelled.
|
|
49
|
+
*
|
|
50
|
+
* `input` and `output` default to this process's, and are parameters for the
|
|
51
|
+
* same reason every clack prompt takes them: a prompt is otherwise the one
|
|
52
|
+
* part of a CLI that cannot be driven by a test.
|
|
53
|
+
*/
|
|
54
|
+
export declare function askForOrg(game: string, registering: boolean, io?: Io): Promise<string | undefined | null>;
|
|
55
|
+
/**
|
|
56
|
+
* Asked only when {@link firebaseReadiness} found something missing, and
|
|
57
|
+
* defaulted to "no" because the honest answer usually is: the tools are two
|
|
58
|
+
* commands away, and the alternative is an app that throws at launch until
|
|
59
|
+
* they are installed anyway.
|
|
60
|
+
*/
|
|
61
|
+
export declare function askToScaffoldWithoutFirebase(io?: Io): Promise<boolean | null>;
|
|
62
|
+
/** Defaulted to yes: the scaffold is a few hundred generated files, and a commit is what makes the first `git diff` the first game change rather than all of them. */
|
|
63
|
+
export declare function askForGit(io?: Io): Promise<boolean | null>;
|
|
64
|
+
/**
|
|
65
|
+
* Defaulted to no, and the hint says why rather than leaving it as an
|
|
66
|
+
* arbitrary-looking choice: `release.yml` needs an upload keystore and a Play
|
|
67
|
+
* service account, so a project that takes the workflows before it has either
|
|
68
|
+
* gets a red `main` from its first push.
|
|
69
|
+
*/
|
|
70
|
+
export declare function askForWorkflows(io?: Io): Promise<boolean | null>;
|
|
71
|
+
/**
|
|
72
|
+
* The package manager, asked only when nothing else could say.
|
|
73
|
+
*
|
|
74
|
+
* `npm create` and `pnpm create` both set `npm_config_user_agent`, so this is
|
|
75
|
+
* reached by the paths that do not: a global install, or running the binary
|
|
76
|
+
* directly. Rare, but it decides what every generated script says, and the old
|
|
77
|
+
* silent fallback to pnpm was a guess printed into a project's package.json.
|
|
78
|
+
*/
|
|
79
|
+
export declare function askForPackageManager(io?: Io): Promise<PackageManager | null>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The closing summary, and the only output of a scaffold anyone reads.
|
|
3
|
+
*
|
|
4
|
+
* A run drives several tools with plenty to say, so where the project went,
|
|
5
|
+
* what to edit, and what to run are worth restating at the bottom. Returned in
|
|
6
|
+
* pieces rather than as one block, because the CLI renders each in a different
|
|
7
|
+
* shape: the outcomes as status lines, the commands as a boxed note, the
|
|
8
|
+
* destination as the closing line.
|
|
9
|
+
*
|
|
10
|
+
* Its own module so it can be asserted: `cli.ts` is the bin entry and runs
|
|
11
|
+
* `main` on import, which makes anything defined there untestable. The package
|
|
12
|
+
* `exports` map does not expose this, so it is internal despite being
|
|
13
|
+
* importable by the tests.
|
|
14
|
+
*/
|
|
15
|
+
import type { PackageManager, ScaffoldResult } from "./index.js";
|
|
16
|
+
export interface Summary {
|
|
17
|
+
/** What became of the repository and of Firebase, when there is something to say. */
|
|
18
|
+
status: string[];
|
|
19
|
+
/** The commands worth having, as one block. */
|
|
20
|
+
next: string;
|
|
21
|
+
/** One-line asides, after the block. */
|
|
22
|
+
footnotes: string[];
|
|
23
|
+
/** The closing line. */
|
|
24
|
+
headline: string;
|
|
25
|
+
}
|
|
26
|
+
export declare function summarise(result: ScaffoldResult, manager: PackageManager, workflows: boolean): Summary;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-eigen-game",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Scaffold an EigenInteractive game Worker and Flutter app without cloning the engine repositories.",
|
|
6
6
|
"type": "module",
|
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/node": "^26.1.1",
|
|
27
27
|
"tsup": "^8.5.1",
|
|
28
|
-
"typescript": "
|
|
28
|
+
"typescript": "~6.0.2",
|
|
29
29
|
"vitest": "^4.1.10",
|
|
30
30
|
"wrangler": "^4.110.0",
|
|
31
31
|
"zod": "^4.4.3",
|
|
32
|
-
"@eigeninteractive/rules": "0.5.
|
|
33
|
-
"@eigeninteractive/
|
|
34
|
-
"@eigeninteractive/
|
|
32
|
+
"@eigeninteractive/rules": "0.5.1",
|
|
33
|
+
"@eigeninteractive/testkit": "0.5.1",
|
|
34
|
+
"@eigeninteractive/server": "0.5.1"
|
|
35
35
|
},
|
|
36
36
|
"engines": {
|
|
37
37
|
"node": ">=22"
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"url": "https://github.com/eigeninteractive/eigen-platform/issues"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
|
-
"build": "tsup src/index.ts src/cli.ts --format esm --
|
|
51
|
+
"build": "tsup src/index.ts src/cli.ts --format esm --sourcemap --clean && tsc -p tsconfig.build.json",
|
|
52
52
|
"test": "vitest run",
|
|
53
53
|
"typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p templates/worker/tsconfig.json"
|
|
54
54
|
}
|