@superzerodev/core 0.1.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.
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Executor(P0設計 §5.2)
3
+ *
4
+ * Change を依存順に実行する。
5
+ *
6
+ * ★ PE-3(部分失敗からの復帰)が最重要:
7
+ * 1件ごとに StateStore へコミットしてから次へ進む。全体をトランザクションで囲まない。
8
+ * 3件目で落ちても、1〜2件目の結果は残る。再実行すれば 3件目から続く。
9
+ * これが「apply を何度でも叩ける」というエージェント前提の運用を成立させる。
10
+ */
11
+ import { SuperzeroError } from './errors.js';
12
+ import type { Logger, SecretResolver } from './adapter.js';
13
+ import type { AdapterRegistry } from './registry.js';
14
+ import type { Change, Plan, ResourceKind, ResourceRecord } from './types.js';
15
+ /**
16
+ * Control Plane DB への永続化境界。
17
+ * core は SQL を知らない。実装は apps/control-plane 側が持つ。
18
+ */
19
+ export interface StateStore {
20
+ /** UNIQUE (environment_id, kind, logical_name) で upsert する(PE-1 の担保) */
21
+ upsert(record: Omit<ResourceRecord, 'id'> & {
22
+ id?: string;
23
+ }): Promise<ResourceRecord>;
24
+ /** update / destroy が必要とする既存 state。未作成なら null */
25
+ load(environmentId: string, kind: ResourceKind, logicalName: string): Promise<ResourceRecord | null>;
26
+ /** plan が必要とする actual state の全件。Planner への入力になる */
27
+ list(environmentId: string): Promise<ResourceRecord[]>;
28
+ remove(environmentId: string, kind: ResourceKind, logicalName: string): Promise<void>;
29
+ /** deployments / changes テーブルへの記録。監査と再開に使う */
30
+ recordChange(deploymentId: string, change: Change, status: 'ok' | 'failed', error?: unknown): Promise<void>;
31
+ }
32
+ export interface ExecuteDeps {
33
+ registry: AdapterRegistry;
34
+ store: StateStore;
35
+ deploymentId: string;
36
+ environmentId: string;
37
+ projectName: string;
38
+ region: string;
39
+ secrets: SecretResolver;
40
+ logger: Logger;
41
+ /** このデプロイのソースが置かれたローカルディレクトリ(ビルドに要る) */
42
+ workspaceDir?: string;
43
+ /** デプロイ対象ソースの内容ハッシュ。plan と同じ値を渡すこと */
44
+ sourceHash?: string | undefined;
45
+ signal?: AbortSignal;
46
+ }
47
+ export interface ExecuteResult {
48
+ applied: Change[];
49
+ skipped: Change[];
50
+ failure?: {
51
+ change: Change;
52
+ error: ReturnType<SuperzeroError['toJSON']>;
53
+ };
54
+ /** resourceKey → 環境変数として注入できる接続情報 */
55
+ outputs: Record<string, Record<string, string>>;
56
+ }
57
+ export declare function execute(plan: Plan, deps: ExecuteDeps): Promise<ExecuteResult>;
58
+ //# sourceMappingURL=executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,cAAc,EAAiC,MAAM,aAAa,CAAA;AAC3E,OAAO,KAAK,EAAkB,MAAM,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC1E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE5E;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,wEAAwE;IACxE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAAA;IACrF,iDAAiD;IACjD,IAAI,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;IACpG,mDAAmD;IACnD,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAA;IACtD,MAAM,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACrF,8CAA8C;IAC9C,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,GAAG,QAAQ,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5G;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,eAAe,CAAA;IACzB,KAAK,EAAE,UAAU,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,cAAc,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,wCAAwC;IACxC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,sCAAsC;IACtC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,OAAO,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAA;KAAE,CAAA;IACzE,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAChD;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAoFnF"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Executor(P0設計 §5.2)
3
+ *
4
+ * Change を依存順に実行する。
5
+ *
6
+ * ★ PE-3(部分失敗からの復帰)が最重要:
7
+ * 1件ごとに StateStore へコミットしてから次へ進む。全体をトランザクションで囲まない。
8
+ * 3件目で落ちても、1〜2件目の結果は残る。再実行すれば 3件目から続く。
9
+ * これが「apply を何度でも叩ける」というエージェント前提の運用を成立させる。
10
+ */
11
+ import { SuperzeroError, isSuperzeroError, wrapUnknown } from './errors.js';
12
+ export async function execute(plan, deps) {
13
+ const { registry, store, logger } = deps;
14
+ const outputs = {};
15
+ const applied = [];
16
+ const remaining = [...plan.changes];
17
+ while (remaining.length > 0) {
18
+ const change = remaining.shift();
19
+ if (!change)
20
+ break;
21
+ if (change.action === 'noop') {
22
+ /**
23
+ * ★ noop でも outputs は組み立てる。
24
+ *
25
+ * ここを飛ばすと、依存側(compute)が DATABASE_URL を受け取れないまま起動する。
26
+ * しかもエラーにならないので、アプリが「DB に繋がらない」状態で
27
+ * 正常にデプロイされたように見える。
28
+ *
29
+ * これは例外的な経路ではなく、最も普通の経路で起きる:
30
+ * - 部分失敗のあとの再実行(DB は作成済み → noop)
31
+ * - アプリのコードだけ変えた再デプロイ(DB は変更なし → noop)
32
+ * つまり2回目以降の apply でほぼ必ず踏む。
33
+ */
34
+ const current = await store.load(deps.environmentId, change.kind, change.logicalName);
35
+ if (current) {
36
+ outputs[change.key] = registry.get(change.kind).outputs(current.state);
37
+ }
38
+ applied.push(change);
39
+ continue;
40
+ }
41
+ const ctx = buildContext(deps, change, outputs);
42
+ const adapter = registry.get(change.kind);
43
+ try {
44
+ deps.signal?.throwIfAborted();
45
+ if (change.action === 'destroy') {
46
+ const current = await requireState(store, deps.environmentId, change);
47
+ await adapter.destroy(current.state, ctx);
48
+ await store.remove(deps.environmentId, change.kind, change.logicalName);
49
+ }
50
+ else {
51
+ const nextState = change.action === 'create'
52
+ ? await adapter.create(change.spec, ctx)
53
+ : await adapter.update(change.spec, (await requireState(store, deps.environmentId, change)).state, ctx);
54
+ await store.upsert({
55
+ environmentId: deps.environmentId,
56
+ kind: change.kind,
57
+ logicalName: change.logicalName,
58
+ provider: change.provider,
59
+ // ★ アダプタに聞く。Control Plane はプロバイダごとの state の形を知らない
60
+ externalId: adapter.externalId(nextState),
61
+ state: nextState,
62
+ status: 'ready',
63
+ });
64
+ outputs[change.key] = adapter.outputs(nextState);
65
+ }
66
+ await store.recordChange(deps.deploymentId, change, 'ok');
67
+ applied.push(change);
68
+ logger.info(`applied ${change.action} ${change.key}`);
69
+ }
70
+ catch (raw) {
71
+ const error = isSuperzeroError(raw) ? raw : wrapUnknown(change.provider, raw);
72
+ await store.recordChange(deps.deploymentId, change, 'failed', error.toJSON());
73
+ logger.error(`failed ${change.action} ${change.key}`, { code: error.code });
74
+ // ここで止める。既に適用済みの分は永続化されているので、再実行で続きから進む。
75
+ return {
76
+ applied,
77
+ skipped: remaining,
78
+ failure: { change, error: error.toJSON() },
79
+ outputs,
80
+ };
81
+ }
82
+ }
83
+ return { applied, skipped: [], outputs };
84
+ }
85
+ function buildContext(deps, change, outputs) {
86
+ const ctx = {
87
+ environmentId: deps.environmentId,
88
+ sourceHash: deps.sourceHash,
89
+ projectName: deps.projectName,
90
+ region: deps.region,
91
+ secrets: deps.secrets,
92
+ logger: deps.logger,
93
+ outputsOf(key) {
94
+ // dependsOn に宣言していない参照は事故のもとなので明示的に弾く
95
+ if (!change.dependsOn.includes(key)) {
96
+ throw new SuperzeroError({
97
+ code: 'PLAN_MISSING_DEPENDENCY',
98
+ message: `Adapter for "${change.key}" requested outputs of "${key}", ` +
99
+ `but "${key}" is not declared in its dependsOn.`,
100
+ suggestedFix: {
101
+ description: `This is an adapter bug, not a configuration problem. ` +
102
+ `Add "${key}" to the dependsOn of the change emitted by the "${change.provider}" adapter.`,
103
+ },
104
+ });
105
+ }
106
+ /**
107
+ * ★ 無いときに {} を返さない。
108
+ *
109
+ * 空を返すと、接続情報が入らないまま起動して「動いているが繋がらない」
110
+ * デプロイができあがる。エラーで止まるほうが必ず良い。
111
+ * 宣言はしたのに解決できていない=こちらの実装の不具合なので、そう書く。
112
+ *
113
+ * なお outputs が空の Record であること自体は正常(接続情報を配らない
114
+ * リソースもある)。区別できるよう、キーの有無で判定している。
115
+ */
116
+ const resolved = outputs[key];
117
+ if (resolved === undefined) {
118
+ throw new SuperzeroError({
119
+ code: 'APPLY_DEPENDENCY_OUTPUTS_MISSING',
120
+ message: `"${change.key}" depends on "${key}", but no outputs were resolved for it. ` +
121
+ `The dependency was neither applied nor loaded during this run.`,
122
+ suggestedFix: {
123
+ description: `This is a bug in Superzero, not in your configuration. ` +
124
+ `Re-running apply is unlikely to help. Please report it with the resource keys above.`,
125
+ command: 'superzero status',
126
+ },
127
+ });
128
+ }
129
+ return resolved;
130
+ },
131
+ };
132
+ if (deps.workspaceDir)
133
+ ctx.workspaceDir = deps.workspaceDir;
134
+ if (deps.signal)
135
+ ctx.signal = deps.signal;
136
+ return ctx;
137
+ }
138
+ /**
139
+ * update / destroy は既存 state を必要とする。
140
+ * plan 時点では在ったが apply 時に消えている=drift。明示的なエラーで止める。
141
+ */
142
+ async function requireState(store, environmentId, change) {
143
+ const record = await store.load(environmentId, change.kind, change.logicalName);
144
+ if (!record) {
145
+ throw new SuperzeroError({
146
+ code: 'APPLY_CHANGE_FAILED',
147
+ message: `Cannot ${change.action} "${change.key}": it no longer exists in the state store. ` +
148
+ `It may have been removed outside of Superzero since the plan was created.`,
149
+ suggestedFix: {
150
+ description: 'Re-run plan to refresh the actual state, then apply again.',
151
+ command: 'superzero plan',
152
+ },
153
+ });
154
+ }
155
+ return record;
156
+ }
157
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * 依存順の解決(PE-2)
3
+ *
4
+ * DB を作ってから接続情報を Compute の env に注入する、という順序を守るために、
5
+ * Change の dependsOn をトポロジカルソートする。
6
+ */
7
+ import type { Change } from './types.js';
8
+ /**
9
+ * Kahn のアルゴリズム。
10
+ * 未宣言の依存があれば missingDependency、閉路があれば circularDependency を throw する。
11
+ * 同順位の Change は key の辞書順で安定させる(plan 出力の再現性のため)。
12
+ */
13
+ export declare function topoSort(changes: Change[]): Change[];
14
+ /**
15
+ * destroy は依存の逆順で実行する。
16
+ * 参照されている側を先に消すと、参照している側の後始末ができなくなるため。
17
+ */
18
+ export declare function orderForDestroy(changes: Change[]): Change[];
19
+ //# sourceMappingURL=graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAExC;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAmDpD;AAsBD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAE3D"}
package/dist/graph.js ADDED
@@ -0,0 +1,92 @@
1
+ /**
2
+ * 依存順の解決(PE-2)
3
+ *
4
+ * DB を作ってから接続情報を Compute の env に注入する、という順序を守るために、
5
+ * Change の dependsOn をトポロジカルソートする。
6
+ */
7
+ import { circularDependency, missingDependency } from './errors.js';
8
+ /**
9
+ * Kahn のアルゴリズム。
10
+ * 未宣言の依存があれば missingDependency、閉路があれば circularDependency を throw する。
11
+ * 同順位の Change は key の辞書順で安定させる(plan 出力の再現性のため)。
12
+ */
13
+ export function topoSort(changes) {
14
+ const byKey = new Map();
15
+ for (const c of changes)
16
+ byKey.set(c.key, c);
17
+ const indegree = new Map();
18
+ const dependents = new Map();
19
+ for (const c of changes) {
20
+ indegree.set(c.key, c.dependsOn.length);
21
+ for (const dep of c.dependsOn) {
22
+ if (!byKey.has(dep))
23
+ throw missingDependency(c.key, dep);
24
+ const list = dependents.get(dep);
25
+ if (list)
26
+ list.push(c.key);
27
+ else
28
+ dependents.set(dep, [c.key]);
29
+ }
30
+ }
31
+ // 依存を持たないものから始める
32
+ const ready = [];
33
+ for (const [key, deg] of indegree) {
34
+ if (deg === 0)
35
+ ready.push(key);
36
+ }
37
+ ready.sort();
38
+ const sorted = [];
39
+ while (ready.length > 0) {
40
+ const key = ready.shift();
41
+ if (key === undefined)
42
+ break;
43
+ const change = byKey.get(key);
44
+ if (change)
45
+ sorted.push(change);
46
+ const next = dependents.get(key) ?? [];
47
+ const unlocked = [];
48
+ for (const d of next) {
49
+ const deg = (indegree.get(d) ?? 0) - 1;
50
+ indegree.set(d, deg);
51
+ if (deg === 0)
52
+ unlocked.push(d);
53
+ }
54
+ if (unlocked.length > 0) {
55
+ unlocked.sort();
56
+ ready.push(...unlocked);
57
+ ready.sort();
58
+ }
59
+ }
60
+ if (sorted.length !== changes.length) {
61
+ const remaining = changes.filter((c) => !sorted.includes(c)).map((c) => c.key);
62
+ throw circularDependency(findCycle(remaining, byKey));
63
+ }
64
+ return sorted;
65
+ }
66
+ /** エラーメッセージに載せる閉路を1つ見つける */
67
+ function findCycle(candidates, byKey) {
68
+ const inCycle = new Set(candidates);
69
+ const start = candidates[0];
70
+ if (start === undefined)
71
+ return candidates;
72
+ const path = [];
73
+ const seen = new Set();
74
+ let current = start;
75
+ while (current !== undefined && !seen.has(current)) {
76
+ seen.add(current);
77
+ path.push(current);
78
+ const change = byKey.get(current);
79
+ current = change?.dependsOn.find((d) => inCycle.has(d));
80
+ }
81
+ if (current !== undefined)
82
+ path.push(current);
83
+ return path;
84
+ }
85
+ /**
86
+ * destroy は依存の逆順で実行する。
87
+ * 参照されている側を先に消すと、参照している側の後始末ができなくなるため。
88
+ */
89
+ export function orderForDestroy(changes) {
90
+ return topoSort(changes).reverse();
91
+ }
92
+ //# sourceMappingURL=graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export * from './types.js';
2
+ export * from './errors.js';
3
+ export * from './source-archive.js';
4
+ export * from './adapter.js';
5
+ export * from './registry.js';
6
+ export * from './graph.js';
7
+ export * from './planner.js';
8
+ export * from './executor.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,qBAAqB,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export * from './types.js';
2
+ export * from './errors.js';
3
+ export * from './source-archive.js';
4
+ export * from './adapter.js';
5
+ export * from './registry.js';
6
+ export * from './graph.js';
7
+ export * from './planner.js';
8
+ export * from './executor.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,qBAAqB,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Planner(P0設計 §5.2)
3
+ *
4
+ * desired(宣言ファイル)と actual(Control Plane DB)の差分から Change[] を組み立てる。
5
+ * 副作用は一切持たない(PE-6)。`superzero plan` はこれを呼ぶだけ。
6
+ */
7
+ import type { AdapterRegistry } from './registry.js';
8
+ import { type Change, type Plan, type ResourceKind, type ResourceRecord } from './types.js';
9
+ /** 宣言ファイルから切り出した1リソース */
10
+ export interface DesiredResource<TSpec = unknown> {
11
+ kind: ResourceKind;
12
+ logicalName: string;
13
+ spec: TSpec;
14
+ }
15
+ export interface PlanOptions {
16
+ /** false のとき、destructive な Change が1件でもあれば throw する(PE-4) */
17
+ allowDestructive?: boolean;
18
+ /** デプロイ対象ソースの内容ハッシュ。アダプタの plan へそのまま渡す */
19
+ sourceHash?: string | undefined;
20
+ }
21
+ export declare function createPlan(registry: AdapterRegistry, desired: DesiredResource[], actual: ResourceRecord[], options?: PlanOptions): Plan;
22
+ /** plan 出力の1行表現。CLI と MCP の両方がこれを使う */
23
+ export declare function formatChange(change: Change): string;
24
+ //# sourceMappingURL=planner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../src/planner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,IAAI,EACT,KAAK,YAAY,EACjB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAA;AAEnB,yBAAyB;AACzB,MAAM,WAAW,eAAe,CAAC,KAAK,GAAG,OAAO;IAC9C,IAAI,EAAE,YAAY,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,KAAK,CAAA;CACZ;AAED,MAAM,WAAW,WAAW;IAC1B,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAChC;AAED,wBAAgB,UAAU,CACxB,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,eAAe,EAAE,EAC1B,MAAM,EAAE,cAAc,EAAE,EACxB,OAAO,GAAE,WAAgB,GACxB,IAAI,CAyCN;AAED,uCAAuC;AACvC,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAWnD"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Planner(P0設計 §5.2)
3
+ *
4
+ * desired(宣言ファイル)と actual(Control Plane DB)の差分から Change[] を組み立てる。
5
+ * 副作用は一切持たない(PE-6)。`superzero plan` はこれを呼ぶだけ。
6
+ */
7
+ import { destructiveChangeBlocked } from './errors.js';
8
+ import { topoSort } from './graph.js';
9
+ import { resourceKey, } from './types.js';
10
+ export function createPlan(registry, desired, actual, options = {}) {
11
+ const desiredByKey = new Map();
12
+ for (const d of desired) {
13
+ desiredByKey.set(resourceKey(d.kind, d.logicalName), d);
14
+ }
15
+ const actualByKey = new Map();
16
+ for (const a of actual) {
17
+ actualByKey.set(resourceKey(a.kind, a.logicalName), a);
18
+ }
19
+ // 両側の和集合を取る。片側にしかないものが create / destroy になる。
20
+ const allKeys = new Set([...desiredByKey.keys(), ...actualByKey.keys()]);
21
+ const changes = [];
22
+ for (const key of [...allKeys].sort()) {
23
+ const d = desiredByKey.get(key);
24
+ const a = actualByKey.get(key);
25
+ // kind と logicalName は必ずどちらかから取れる
26
+ const kind = (d?.kind ?? a?.kind);
27
+ const logicalName = d?.logicalName ?? a?.logicalName ?? '';
28
+ const adapter = registry.get(kind);
29
+ const produced = adapter.plan({
30
+ logicalName,
31
+ desired: (d?.spec ?? null),
32
+ actual: (a ?? null),
33
+ sourceHash: options.sourceHash,
34
+ });
35
+ changes.push(...produced);
36
+ }
37
+ const ordered = topoSort(changes);
38
+ const destructiveKeys = ordered.filter((c) => c.destructive).map((c) => c.key);
39
+ if (destructiveKeys.length > 0 && options.allowDestructive !== true) {
40
+ throw destructiveChangeBlocked(destructiveKeys);
41
+ }
42
+ return { changes: ordered, ordered: true, destructiveKeys };
43
+ }
44
+ /** plan 出力の1行表現。CLI と MCP の両方がこれを使う */
45
+ export function formatChange(change) {
46
+ const sign = change.action === 'create'
47
+ ? '+'
48
+ : change.action === 'destroy'
49
+ ? '-'
50
+ : change.action === 'update'
51
+ ? '~'
52
+ : ' ';
53
+ const flag = change.destructive ? ' [destructive]' : '';
54
+ return `${sign} ${change.key} (${change.provider}) — ${change.summary}${flag}`;
55
+ }
56
+ //# sourceMappingURL=planner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner.js","sourceRoot":"","sources":["../src/planner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * アダプタ登録簿
3
+ *
4
+ * kind ごとに1つのアダプタを選ぶ。差し替えはここ1箇所で完結する。
5
+ * P0: compute → docker, database → neon
6
+ * P1: compute → firecracker, database → superzero-postgres
7
+ */
8
+ import type { ProviderAdapter } from './adapter.js';
9
+ import type { ResourceKind } from './types.js';
10
+ export declare class AdapterRegistry {
11
+ #private;
12
+ register<TSpec, TState>(adapter: ProviderAdapter<TSpec, TState>): this;
13
+ /** 見つからない場合は suggestedFix つきで throw する */
14
+ get(kind: ResourceKind): ProviderAdapter<never, never>;
15
+ has(kind: ResourceKind): boolean;
16
+ kinds(): ResourceKind[];
17
+ }
18
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,qBAAa,eAAe;;IAG1B,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,IAAI;IAKtE,0CAA0C;IAC1C,GAAG,CAAC,IAAI,EAAE,YAAY,GAAG,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC;IAiBtD,GAAG,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO;IAIhC,KAAK,IAAI,YAAY,EAAE;CAGxB"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * アダプタ登録簿
3
+ *
4
+ * kind ごとに1つのアダプタを選ぶ。差し替えはここ1箇所で完結する。
5
+ * P0: compute → docker, database → neon
6
+ * P1: compute → firecracker, database → superzero-postgres
7
+ */
8
+ import { SuperzeroError, ErrorCode } from './errors.js';
9
+ export class AdapterRegistry {
10
+ #byKind = new Map();
11
+ register(adapter) {
12
+ this.#byKind.set(adapter.kind, adapter);
13
+ return this;
14
+ }
15
+ /** 見つからない場合は suggestedFix つきで throw する */
16
+ get(kind) {
17
+ const adapter = this.#byKind.get(kind);
18
+ if (!adapter) {
19
+ throw new SuperzeroError({
20
+ code: ErrorCode.CONFIG_UNKNOWN_PROVIDER,
21
+ message: `No provider adapter is registered for resource kind "${kind}".`,
22
+ suggestedFix: {
23
+ description: `Remove the "${kind}" block from superzero.config.ts, ` +
24
+ `or upgrade the CLI if this resource kind was added in a newer version.`,
25
+ command: 'npm install -g @superzerodev/cli@latest',
26
+ },
27
+ });
28
+ }
29
+ return adapter;
30
+ }
31
+ has(kind) {
32
+ return this.#byKind.has(kind);
33
+ }
34
+ kinds() {
35
+ return [...this.#byKind.keys()];
36
+ }
37
+ }
38
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAIvD,MAAM,OAAO,eAAe;IACjB,OAAO,GAAG,IAAI,GAAG,EAA+C,CAAA;IAEzE,QAAQ,CAAgB,OAAuC;QAC7D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAmD,CAAC,CAAA;QACnF,OAAO,IAAI,CAAA;IACb,CAAC;IAED,0CAA0C;IAC1C,GAAG,CAAC,IAAkB;QACpB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACtC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,cAAc,CAAC;gBACvB,IAAI,EAAE,SAAS,CAAC,uBAAuB;gBACvC,OAAO,EAAE,wDAAwD,IAAI,IAAI;gBACzE,YAAY,EAAE;oBACZ,WAAW,EACT,eAAe,IAAI,oCAAoC;wBACvD,wEAAwE;oBAC1E,OAAO,EAAE,yCAAyC;iBACnD;aACF,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,GAAG,CAAC,IAAkB;QACpB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC/B,CAAC;IAED,KAAK;QACH,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IACjC,CAAC;CACF"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * デプロイするソースの受け渡し(CLI → Control Plane)
3
+ *
4
+ * ★ ここが無いと、遠隔の顧客は誰もアプリを載せられない。
5
+ *
6
+ * 以前は CLI が「宣言ファイルのあるディレクトリの絶対パス」を文字列で送り、
7
+ * Control Plane がそれを *自分の* ファイルシステムのパスとして開いていた。
8
+ * CLI とサーバーが同じホストに居るときだけ通る作りで、顧客の Mac から
9
+ * api.superzero.dev を叩くと `ENOENT ... scandir '/Users/...'` で落ちていた。
10
+ * 受け入れ確認が通っていたのは、CLI をサーバー上で走らせていたため。
11
+ *
12
+ * 加えて、そのパスは無検証でサーバーの fs に渡っていた。認証済みの顧客が
13
+ * `/etc/superzero` を指定すれば、基盤の秘密が自分のコンテナイメージに入った。
14
+ * ソースを送る形にすると、この穴は構造的に消える(パスを受け取らなくなる)。
15
+ *
16
+ * ★ 外部依存を足さない。tar は自分で書く。
17
+ * 顧客の手元で走るコードなので、依存が増えるほど「入らない」が増える。
18
+ * 形式は ustar(長い名前は GNU の 'L' エントリ)なので、
19
+ * `tar -tzf` でそのまま中身を確認できる。デバッグ手段を捨てない。
20
+ *
21
+ * ★ macOS の tar を呼ばない。
22
+ * 呼ぶと拡張属性が `._<name>` という別ファイルとして混ざり、Linux 側の
23
+ * Nixpacks が "stream did not contain valid UTF-8" で落ちる
24
+ * (docs/05-development.md の「macOS の tar が AppleDouble を混ぜる」)。
25
+ * 自分で書けば構造的に混ざらない。既にディスク上にある `._*` は明示的に外す。
26
+ */
27
+ /**
28
+ * ビルドに関係しないので送らない。ソースの指紋(fingerprintOf)の
29
+ * 除外リストと同じ集合であること。ここがずれると、送っていないファイルを
30
+ * サーバーが数えようとして指紋が食い違う。
31
+ */
32
+ export declare const DEFAULT_IGNORED_ENTRIES: ReadonlySet<string>;
33
+ /**
34
+ * 名前だけで落とせるものを落とす。
35
+ *
36
+ * ★ `._*`(AppleDouble)は集合ではなく前置きで判定する。
37
+ * 名前が実行時に決まるので Set には入れられない。
38
+ */
39
+ export declare function isIgnoredEntryName(name: string): boolean;
40
+ export interface SourceLimits {
41
+ /** 送れるファイル数の上限 */
42
+ maxFiles: number;
43
+ /** 展開後の合計バイト数の上限。圧縮後ではなく展開後で数える(zip bomb 対策) */
44
+ maxBytes: number;
45
+ }
46
+ /**
47
+ * 上限。node_modules を外したアプリのソースとしては十分に広い。
48
+ * 超えるのはたいてい「送るべきでないもの」が混ざっている合図なので、
49
+ * 黙って通さずエラーにして気づかせる。
50
+ */
51
+ export declare const DEFAULT_SOURCE_LIMITS: SourceLimits;
52
+ export interface PackedSource {
53
+ /** gzip 済みの tar */
54
+ archive: Uint8Array;
55
+ fileCount: number;
56
+ /** 展開後の合計バイト数 */
57
+ bytes: number;
58
+ /** ファイルの選び方。利用者に「何を送ったか」を説明するために返す */
59
+ selection: 'git' | 'walk';
60
+ }
61
+ export interface PackOptions {
62
+ limits?: SourceLimits;
63
+ /** git の呼び出しを諦めるまでの時間。既定 10 秒 */
64
+ gitTimeoutMs?: number;
65
+ /** テスト用に git を使わせない */
66
+ useGit?: boolean;
67
+ }
68
+ export declare function packSource(rootDir: string, options?: PackOptions): Promise<PackedSource>;
69
+ export interface UnpackedSource {
70
+ fileCount: number;
71
+ bytes: number;
72
+ }
73
+ /**
74
+ * アーカイブを destDir に展開する。
75
+ *
76
+ * ★ 中身は顧客が作ったもの。信用しない。
77
+ * 絶対パス・`..`・シンボリックリンク・デバイスファイルは全て拒否する。
78
+ * 通したら、顧客が Control Plane のホストの任意の場所に書けることになる。
79
+ *
80
+ * ★ 上限は「宣言されたサイズ」ではなく「実際に展開したバイト数」で数える。
81
+ * ヘッダの数字を信じると、小さいと宣言した巨大なアーカイブを通してしまう。
82
+ */
83
+ export declare function unpackSource(archive: Uint8Array, destDir: string, limits?: SourceLimits): Promise<UnpackedSource>;
84
+ export declare function formatBytes(bytes: number): string;
85
+ //# sourceMappingURL=source-archive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-archive.d.ts","sourceRoot":"","sources":["../src/source-archive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AASH;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAWtD,CAAA;AAEF;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,MAAM,WAAW,YAAY;IAC3B,kBAAkB;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,YAGnC,CAAA;AAED,MAAM,WAAW,YAAY;IAC3B,mBAAmB;IACnB,OAAO,EAAE,UAAU,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,sCAAsC;IACtC,SAAS,EAAE,KAAK,GAAG,MAAM,CAAA;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,uBAAuB;IACvB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AA0HD,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAqClG;AA0DD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,UAAU,EACnB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,YAAoC,GAC3C,OAAO,CAAC,cAAc,CAAC,CAsEzB;AAqED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjD"}