@stardeck-customer-apps/compose 0.2.0 → 0.3.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/SKILL.md +10 -6
- package/dist/cli.js +225 -153
- package/dist/index.d.mts +33 -20
- package/dist/index.d.ts +33 -20
- package/dist/index.js +225 -153
- package/dist/index.mjs +225 -153
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2029,6 +2029,29 @@ var initialModuleCompositionSchema = z6.object({
|
|
|
2029
2029
|
});
|
|
2030
2030
|
var MODULE_SETUP_ATTEMPT_STALE_MS = 10 * 60 * 1e3;
|
|
2031
2031
|
|
|
2032
|
+
// ../../packages/lib/src/shared/compose-inputs.ts
|
|
2033
|
+
import { z as z7 } from "zod";
|
|
2034
|
+
var COMPOSE_INPUTS_PATH = "apps/web/stardeck.compose.json";
|
|
2035
|
+
var composeInputsSchema = z7.strictObject({
|
|
2036
|
+
connectedStores: z7.array(
|
|
2037
|
+
z7.strictObject({
|
|
2038
|
+
storeId: z7.string().min(1),
|
|
2039
|
+
slug: z7.string().min(1),
|
|
2040
|
+
// A row with an empty binding key must not fail a deploy: the rail
|
|
2041
|
+
// treats falsy as "no binding key", so normalise rather than reject.
|
|
2042
|
+
bindingKey: z7.string().nullish().transform((value) => value || null),
|
|
2043
|
+
accessLevel: z7.enum(["read", "write", "admin"])
|
|
2044
|
+
})
|
|
2045
|
+
).default([]),
|
|
2046
|
+
installs: z7.record(
|
|
2047
|
+
z7.string(),
|
|
2048
|
+
z7.strictObject({
|
|
2049
|
+
installedVersion: z7.string().min(1),
|
|
2050
|
+
datastoreBindings: z7.record(z7.string(), z7.string()).nullish()
|
|
2051
|
+
})
|
|
2052
|
+
).default({})
|
|
2053
|
+
});
|
|
2054
|
+
|
|
2032
2055
|
// ../../packages/lib/src/shared/module-enablement.ts
|
|
2033
2056
|
function isModuleEnabledByList(raw, name, kindOf) {
|
|
2034
2057
|
if (!raw) return true;
|
|
@@ -3530,6 +3553,27 @@ function dirnamePosix(filePath) {
|
|
|
3530
3553
|
return idx <= 0 ? "." : filePath.slice(0, idx);
|
|
3531
3554
|
}
|
|
3532
3555
|
|
|
3556
|
+
// ../../packages/lib/src/server/module-rail/compose-inputs.ts
|
|
3557
|
+
async function buildComposeInputs(input) {
|
|
3558
|
+
const { db, projectId, deps } = input;
|
|
3559
|
+
const connectedStores = await deps.listDatabaseStoresForProject(db, projectId);
|
|
3560
|
+
const installRows = await Promise.all(
|
|
3561
|
+
input.moduleNames.map(async (moduleName) => ({
|
|
3562
|
+
moduleName,
|
|
3563
|
+
install: await deps.getModuleInstall(db, projectId, moduleName)
|
|
3564
|
+
}))
|
|
3565
|
+
);
|
|
3566
|
+
const installs = {};
|
|
3567
|
+
for (const { moduleName, install } of installRows) {
|
|
3568
|
+
if (!install) continue;
|
|
3569
|
+
installs[moduleName] = {
|
|
3570
|
+
installedVersion: install.installedVersion,
|
|
3571
|
+
datastoreBindings: install.datastoreBindings ?? null
|
|
3572
|
+
};
|
|
3573
|
+
}
|
|
3574
|
+
return composeInputsSchema.parse({ connectedStores, installs });
|
|
3575
|
+
}
|
|
3576
|
+
|
|
3533
3577
|
// ../../packages/lib/src/shared/data-store-manifest.ts
|
|
3534
3578
|
function dataStoreSlug(name) {
|
|
3535
3579
|
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
@@ -3726,162 +3770,162 @@ function rejectPseudoModuleEntries(entries, parentDir, label) {
|
|
|
3726
3770
|
}
|
|
3727
3771
|
|
|
3728
3772
|
// ../../packages/lib/src/shared/schema-ops.ts
|
|
3729
|
-
import { z as
|
|
3730
|
-
var columnSpecSchema =
|
|
3731
|
-
name:
|
|
3732
|
-
pgType:
|
|
3733
|
-
nullable:
|
|
3773
|
+
import { z as z8 } from "zod";
|
|
3774
|
+
var columnSpecSchema = z8.object({
|
|
3775
|
+
name: z8.string().min(1).max(63),
|
|
3776
|
+
pgType: z8.string().min(1),
|
|
3777
|
+
nullable: z8.boolean(),
|
|
3734
3778
|
/**
|
|
3735
3779
|
* A SQL expression used as the column default, as a raw string (e.g. `'t'`,
|
|
3736
3780
|
* `0`, `now()`, `gen_random_uuid()`). `null` or omitted means no default.
|
|
3737
3781
|
* NOT a JS literal — must already be a valid SQL expression.
|
|
3738
3782
|
*/
|
|
3739
|
-
default:
|
|
3740
|
-
fieldType:
|
|
3741
|
-
fieldConfig:
|
|
3783
|
+
default: z8.string().nullable().optional(),
|
|
3784
|
+
fieldType: z8.string().optional(),
|
|
3785
|
+
fieldConfig: z8.record(z8.string(), z8.unknown()).optional()
|
|
3742
3786
|
});
|
|
3743
|
-
var referentialActionSchema =
|
|
3787
|
+
var referentialActionSchema = z8.enum([
|
|
3744
3788
|
"cascade",
|
|
3745
3789
|
"set null",
|
|
3746
3790
|
"set default",
|
|
3747
3791
|
"restrict",
|
|
3748
3792
|
"no action"
|
|
3749
3793
|
]);
|
|
3750
|
-
var schemaOpSchema =
|
|
3794
|
+
var schemaOpSchema = z8.discriminatedUnion("type", [
|
|
3751
3795
|
// Tables
|
|
3752
|
-
|
|
3753
|
-
type:
|
|
3754
|
-
table:
|
|
3755
|
-
columns:
|
|
3756
|
-
primaryKey:
|
|
3757
|
-
ifNotExists:
|
|
3796
|
+
z8.object({
|
|
3797
|
+
type: z8.literal("createTable"),
|
|
3798
|
+
table: z8.string().min(1).max(63),
|
|
3799
|
+
columns: z8.array(columnSpecSchema).min(1),
|
|
3800
|
+
primaryKey: z8.array(z8.string()).optional(),
|
|
3801
|
+
ifNotExists: z8.boolean().optional()
|
|
3758
3802
|
}),
|
|
3759
|
-
|
|
3760
|
-
type:
|
|
3761
|
-
table:
|
|
3762
|
-
cascade:
|
|
3763
|
-
ifExists:
|
|
3803
|
+
z8.object({
|
|
3804
|
+
type: z8.literal("dropTable"),
|
|
3805
|
+
table: z8.string().min(1).max(63),
|
|
3806
|
+
cascade: z8.boolean().optional(),
|
|
3807
|
+
ifExists: z8.boolean().optional()
|
|
3764
3808
|
}),
|
|
3765
|
-
|
|
3766
|
-
type:
|
|
3767
|
-
from:
|
|
3768
|
-
to:
|
|
3809
|
+
z8.object({
|
|
3810
|
+
type: z8.literal("renameTable"),
|
|
3811
|
+
from: z8.string().min(1).max(63),
|
|
3812
|
+
to: z8.string().min(1).max(63)
|
|
3769
3813
|
}),
|
|
3770
3814
|
// Columns
|
|
3771
|
-
|
|
3772
|
-
type:
|
|
3773
|
-
table:
|
|
3815
|
+
z8.object({
|
|
3816
|
+
type: z8.literal("addColumn"),
|
|
3817
|
+
table: z8.string().min(1).max(63),
|
|
3774
3818
|
column: columnSpecSchema,
|
|
3775
|
-
ifNotExists:
|
|
3819
|
+
ifNotExists: z8.boolean().optional()
|
|
3776
3820
|
}),
|
|
3777
|
-
|
|
3778
|
-
type:
|
|
3779
|
-
table:
|
|
3780
|
-
column:
|
|
3781
|
-
cascade:
|
|
3782
|
-
ifExists:
|
|
3821
|
+
z8.object({
|
|
3822
|
+
type: z8.literal("dropColumn"),
|
|
3823
|
+
table: z8.string().min(1).max(63),
|
|
3824
|
+
column: z8.string().min(1).max(63),
|
|
3825
|
+
cascade: z8.boolean().optional(),
|
|
3826
|
+
ifExists: z8.boolean().optional()
|
|
3783
3827
|
}),
|
|
3784
|
-
|
|
3785
|
-
type:
|
|
3786
|
-
table:
|
|
3787
|
-
from:
|
|
3788
|
-
to:
|
|
3828
|
+
z8.object({
|
|
3829
|
+
type: z8.literal("renameColumn"),
|
|
3830
|
+
table: z8.string().min(1).max(63),
|
|
3831
|
+
from: z8.string().min(1).max(63),
|
|
3832
|
+
to: z8.string().min(1).max(63)
|
|
3789
3833
|
}),
|
|
3790
|
-
|
|
3791
|
-
type:
|
|
3792
|
-
table:
|
|
3793
|
-
column:
|
|
3794
|
-
newType:
|
|
3834
|
+
z8.object({
|
|
3835
|
+
type: z8.literal("alterColumnType"),
|
|
3836
|
+
table: z8.string().min(1).max(63),
|
|
3837
|
+
column: z8.string().min(1).max(63),
|
|
3838
|
+
newType: z8.string().min(1),
|
|
3795
3839
|
/** Optional USING expression for potentially-lossy casts */
|
|
3796
|
-
using:
|
|
3840
|
+
using: z8.string().optional()
|
|
3797
3841
|
}),
|
|
3798
|
-
|
|
3799
|
-
type:
|
|
3800
|
-
table:
|
|
3801
|
-
column:
|
|
3802
|
-
nullable:
|
|
3842
|
+
z8.object({
|
|
3843
|
+
type: z8.literal("alterColumnNullable"),
|
|
3844
|
+
table: z8.string().min(1).max(63),
|
|
3845
|
+
column: z8.string().min(1).max(63),
|
|
3846
|
+
nullable: z8.boolean()
|
|
3803
3847
|
}),
|
|
3804
|
-
|
|
3805
|
-
type:
|
|
3806
|
-
table:
|
|
3807
|
-
column:
|
|
3848
|
+
z8.object({
|
|
3849
|
+
type: z8.literal("alterColumnDefault"),
|
|
3850
|
+
table: z8.string().min(1).max(63),
|
|
3851
|
+
column: z8.string().min(1).max(63),
|
|
3808
3852
|
/** null means drop the default; otherwise a SQL expression string. */
|
|
3809
|
-
default:
|
|
3853
|
+
default: z8.string().nullable()
|
|
3810
3854
|
}),
|
|
3811
3855
|
// Indexes
|
|
3812
|
-
|
|
3813
|
-
type:
|
|
3814
|
-
table:
|
|
3815
|
-
name:
|
|
3816
|
-
columns:
|
|
3817
|
-
unique:
|
|
3856
|
+
z8.object({
|
|
3857
|
+
type: z8.literal("addIndex"),
|
|
3858
|
+
table: z8.string().min(1).max(63),
|
|
3859
|
+
name: z8.string().min(1).max(63),
|
|
3860
|
+
columns: z8.array(z8.string().min(1)).min(1),
|
|
3861
|
+
unique: z8.boolean().optional(),
|
|
3818
3862
|
/** Partial-index WHERE clause, as a raw SQL expression */
|
|
3819
|
-
where:
|
|
3820
|
-
ifNotExists:
|
|
3863
|
+
where: z8.string().optional(),
|
|
3864
|
+
ifNotExists: z8.boolean().optional()
|
|
3821
3865
|
}),
|
|
3822
|
-
|
|
3823
|
-
type:
|
|
3824
|
-
name:
|
|
3825
|
-
cascade:
|
|
3826
|
-
ifExists:
|
|
3866
|
+
z8.object({
|
|
3867
|
+
type: z8.literal("dropIndex"),
|
|
3868
|
+
name: z8.string().min(1).max(63),
|
|
3869
|
+
cascade: z8.boolean().optional(),
|
|
3870
|
+
ifExists: z8.boolean().optional()
|
|
3827
3871
|
}),
|
|
3828
3872
|
// Constraints
|
|
3829
|
-
|
|
3830
|
-
type:
|
|
3831
|
-
table:
|
|
3832
|
-
name:
|
|
3833
|
-
columns:
|
|
3834
|
-
refTable:
|
|
3835
|
-
refColumns:
|
|
3873
|
+
z8.object({
|
|
3874
|
+
type: z8.literal("addForeignKey"),
|
|
3875
|
+
table: z8.string().min(1).max(63),
|
|
3876
|
+
name: z8.string().min(1).max(63),
|
|
3877
|
+
columns: z8.array(z8.string().min(1)).min(1),
|
|
3878
|
+
refTable: z8.string().min(1).max(63),
|
|
3879
|
+
refColumns: z8.array(z8.string().min(1)).min(1),
|
|
3836
3880
|
onDelete: referentialActionSchema.optional(),
|
|
3837
3881
|
onUpdate: referentialActionSchema.optional()
|
|
3838
3882
|
}),
|
|
3839
|
-
|
|
3840
|
-
type:
|
|
3841
|
-
table:
|
|
3842
|
-
name:
|
|
3843
|
-
columns:
|
|
3883
|
+
z8.object({
|
|
3884
|
+
type: z8.literal("addUniqueConstraint"),
|
|
3885
|
+
table: z8.string().min(1).max(63),
|
|
3886
|
+
name: z8.string().min(1).max(63),
|
|
3887
|
+
columns: z8.array(z8.string().min(1)).min(1)
|
|
3844
3888
|
}),
|
|
3845
|
-
|
|
3846
|
-
type:
|
|
3847
|
-
table:
|
|
3848
|
-
name:
|
|
3849
|
-
expression:
|
|
3889
|
+
z8.object({
|
|
3890
|
+
type: z8.literal("addCheckConstraint"),
|
|
3891
|
+
table: z8.string().min(1).max(63),
|
|
3892
|
+
name: z8.string().min(1).max(63),
|
|
3893
|
+
expression: z8.string().min(1)
|
|
3850
3894
|
}),
|
|
3851
|
-
|
|
3852
|
-
type:
|
|
3853
|
-
table:
|
|
3854
|
-
name:
|
|
3855
|
-
cascade:
|
|
3856
|
-
ifExists:
|
|
3895
|
+
z8.object({
|
|
3896
|
+
type: z8.literal("dropConstraint"),
|
|
3897
|
+
table: z8.string().min(1).max(63),
|
|
3898
|
+
name: z8.string().min(1).max(63),
|
|
3899
|
+
cascade: z8.boolean().optional(),
|
|
3900
|
+
ifExists: z8.boolean().optional()
|
|
3857
3901
|
}),
|
|
3858
3902
|
// Enum types
|
|
3859
|
-
|
|
3860
|
-
type:
|
|
3861
|
-
name:
|
|
3862
|
-
values:
|
|
3903
|
+
z8.object({
|
|
3904
|
+
type: z8.literal("createEnum"),
|
|
3905
|
+
name: z8.string().min(1).max(63),
|
|
3906
|
+
values: z8.array(z8.string().min(1)).min(1)
|
|
3863
3907
|
}),
|
|
3864
|
-
|
|
3865
|
-
type:
|
|
3866
|
-
name:
|
|
3867
|
-
value:
|
|
3908
|
+
z8.object({
|
|
3909
|
+
type: z8.literal("alterEnumAddValue"),
|
|
3910
|
+
name: z8.string().min(1).max(63),
|
|
3911
|
+
value: z8.string().min(1),
|
|
3868
3912
|
/** Position the new value before an existing one (mutually exclusive with `after`) */
|
|
3869
|
-
before:
|
|
3913
|
+
before: z8.string().optional(),
|
|
3870
3914
|
/** Position the new value after an existing one (mutually exclusive with `before`) */
|
|
3871
|
-
after:
|
|
3872
|
-
ifNotExists:
|
|
3915
|
+
after: z8.string().optional(),
|
|
3916
|
+
ifNotExists: z8.boolean().optional()
|
|
3873
3917
|
}),
|
|
3874
|
-
|
|
3875
|
-
type:
|
|
3876
|
-
name:
|
|
3877
|
-
cascade:
|
|
3878
|
-
ifExists:
|
|
3918
|
+
z8.object({
|
|
3919
|
+
type: z8.literal("dropEnum"),
|
|
3920
|
+
name: z8.string().min(1).max(63),
|
|
3921
|
+
cascade: z8.boolean().optional(),
|
|
3922
|
+
ifExists: z8.boolean().optional()
|
|
3879
3923
|
}),
|
|
3880
3924
|
// Extensions
|
|
3881
|
-
|
|
3882
|
-
type:
|
|
3883
|
-
name:
|
|
3884
|
-
ifNotExists:
|
|
3925
|
+
z8.object({
|
|
3926
|
+
type: z8.literal("createExtension"),
|
|
3927
|
+
name: z8.string().min(1),
|
|
3928
|
+
ifNotExists: z8.boolean().optional()
|
|
3885
3929
|
}),
|
|
3886
3930
|
// Data operations
|
|
3887
3931
|
/**
|
|
@@ -3889,26 +3933,26 @@ var schemaOpSchema = z7.discriminatedUnion("type", [
|
|
|
3889
3933
|
* destructive — requires explicit confirm to replay on prod. The
|
|
3890
3934
|
* `description` is what the agent/user sees at confirm time.
|
|
3891
3935
|
*/
|
|
3892
|
-
|
|
3893
|
-
type:
|
|
3894
|
-
description:
|
|
3895
|
-
sql:
|
|
3936
|
+
z8.object({
|
|
3937
|
+
type: z8.literal("backfill"),
|
|
3938
|
+
description: z8.string().min(1),
|
|
3939
|
+
sql: z8.string().min(1)
|
|
3896
3940
|
}),
|
|
3897
3941
|
/**
|
|
3898
3942
|
* Escape hatch for DDL the structured ops can't express. `destructive`
|
|
3899
3943
|
* forces classification — use false only for genuinely additive-only SQL
|
|
3900
3944
|
* (e.g. CREATE EXTENSION variants the structured op doesn't cover).
|
|
3901
3945
|
*/
|
|
3902
|
-
|
|
3903
|
-
type:
|
|
3904
|
-
description:
|
|
3905
|
-
sql:
|
|
3906
|
-
destructive:
|
|
3946
|
+
z8.object({
|
|
3947
|
+
type: z8.literal("rawSql"),
|
|
3948
|
+
description: z8.string().min(1),
|
|
3949
|
+
sql: z8.string().min(1),
|
|
3950
|
+
destructive: z8.boolean()
|
|
3907
3951
|
})
|
|
3908
3952
|
]);
|
|
3909
3953
|
|
|
3910
3954
|
// ../../packages/lib/src/server/module-rail/ops.ts
|
|
3911
|
-
import { z as
|
|
3955
|
+
import { z as z9 } from "zod";
|
|
3912
3956
|
|
|
3913
3957
|
// ../../packages/lib/src/server/module-rail/reconcile.ts
|
|
3914
3958
|
var SANDBOX_BATCH_SIZE = 200;
|
|
@@ -3949,8 +3993,8 @@ function countedCompositionContext(context) {
|
|
|
3949
3993
|
}
|
|
3950
3994
|
};
|
|
3951
3995
|
}
|
|
3952
|
-
async function listPresentModuleNames(
|
|
3953
|
-
const entries = await listImmediateEntries(
|
|
3996
|
+
async function listPresentModuleNames(sandbox) {
|
|
3997
|
+
const entries = await listImmediateEntries(sandbox, MODULES_SANDBOX_DIR, {
|
|
3954
3998
|
optional: true,
|
|
3955
3999
|
label: "modules"
|
|
3956
4000
|
});
|
|
@@ -4154,24 +4198,24 @@ async function discoverModuleRouteEntries(context, moduleName) {
|
|
|
4154
4198
|
}
|
|
4155
4199
|
return pages.sort((a, b) => a.nextRelativePath.localeCompare(b.nextRelativePath));
|
|
4156
4200
|
}
|
|
4157
|
-
async function writeSandboxFileAtomic(
|
|
4201
|
+
async function writeSandboxFileAtomic(target, path3, content) {
|
|
4158
4202
|
const dir = dirnamePosix(path3);
|
|
4159
|
-
const tmp = `${path3}.tmp.${
|
|
4203
|
+
const tmp = `${path3}.tmp.${target.runId}`;
|
|
4160
4204
|
const b64 = Buffer.from(content, "utf8").toString("base64");
|
|
4161
4205
|
const cmd = [
|
|
4162
4206
|
`mkdir -p ${shellQuote(dir)}`,
|
|
4163
4207
|
`printf '%s' ${shellQuote(b64)} | base64 -d > ${shellQuote(tmp)}`,
|
|
4164
4208
|
`mv -f ${shellQuote(tmp)} ${shellQuote(path3)}`
|
|
4165
4209
|
].join(" && ");
|
|
4166
|
-
const result = await
|
|
4210
|
+
const result = await target.sandbox.exec(cmd, { raiseOnError: false });
|
|
4167
4211
|
if (result.exitCode !== 0) {
|
|
4168
|
-
const cleanup = await
|
|
4212
|
+
const cleanup = await target.sandbox.exec(`rm -f ${shellQuote(tmp)}`, {
|
|
4169
4213
|
raiseOnError: false
|
|
4170
4214
|
});
|
|
4171
4215
|
if (cleanup.exitCode !== 0) {
|
|
4172
4216
|
const cleanupDetail = typeof cleanup.error === "string" && cleanup.error.trim() || cleanup.output.trim() || `exit ${cleanup.exitCode}`;
|
|
4173
4217
|
console.log(
|
|
4174
|
-
`[ModuleRail] runId=${
|
|
4218
|
+
`[ModuleRail] runId=${target.runId} composition artifacts failed to clean temp ${redactSecrets(tmp)}: ${redactSecrets(cleanupDetail)}`
|
|
4175
4219
|
);
|
|
4176
4220
|
}
|
|
4177
4221
|
const detail = typeof result.error === "string" && result.error.trim() || result.output.trim() || `exit ${result.exitCode}`;
|
|
@@ -4229,6 +4273,40 @@ async function deleteSandboxFile(context, path3) {
|
|
|
4229
4273
|
);
|
|
4230
4274
|
}
|
|
4231
4275
|
}
|
|
4276
|
+
async function writeComposeInputs(target) {
|
|
4277
|
+
const ignored = await target.sandbox.exec(
|
|
4278
|
+
`git check-ignore -q ${shellQuote(COMPOSE_INPUTS_PATH)}`,
|
|
4279
|
+
{ raiseOnError: false }
|
|
4280
|
+
);
|
|
4281
|
+
if (ignored.exitCode === 1) {
|
|
4282
|
+
console.log(
|
|
4283
|
+
`[ComposeInputs] project=${target.projectId} skipped: ${COMPOSE_INPUTS_PATH} is not ignored in this checkout`
|
|
4284
|
+
);
|
|
4285
|
+
return false;
|
|
4286
|
+
}
|
|
4287
|
+
if (ignored.exitCode !== 0) {
|
|
4288
|
+
const detail = typeof ignored.error === "string" && ignored.error.trim() || ignored.output.trim() || "(no output)";
|
|
4289
|
+
throw new Error(
|
|
4290
|
+
`[ComposeInputs] git check-ignore failed in this checkout (exit ${ignored.exitCode}): ${redactSecrets(detail)}`
|
|
4291
|
+
);
|
|
4292
|
+
}
|
|
4293
|
+
const moduleNames = await listPresentModuleNames(target.sandbox);
|
|
4294
|
+
const inputs = await buildComposeInputs({
|
|
4295
|
+
db: target.db,
|
|
4296
|
+
projectId: target.projectId,
|
|
4297
|
+
deps: target.deps,
|
|
4298
|
+
moduleNames
|
|
4299
|
+
});
|
|
4300
|
+
const content = `${JSON.stringify(inputs, null, 2)}
|
|
4301
|
+
`;
|
|
4302
|
+
const existing = await target.sandbox.fileExists(COMPOSE_INPUTS_PATH) ? await target.sandbox.readFile(COMPOSE_INPUTS_PATH) : null;
|
|
4303
|
+
const written = existing === null || existing.trimEnd() !== content.trimEnd();
|
|
4304
|
+
if (written) await writeSandboxFileAtomic(target, COMPOSE_INPUTS_PATH, content);
|
|
4305
|
+
console.log(
|
|
4306
|
+
`[ComposeInputs] project=${target.projectId} stores=${inputs.connectedStores.length} installs=${Object.keys(inputs.installs).length} written=${written}`
|
|
4307
|
+
);
|
|
4308
|
+
return written;
|
|
4309
|
+
}
|
|
4232
4310
|
async function applyCompositionArtifactMutations(context, plan, existingFiles) {
|
|
4233
4311
|
const appliedWrites = [];
|
|
4234
4312
|
const appliedDeletes = [];
|
|
@@ -4864,7 +4942,7 @@ async function reconcileCompositionArtifacts(context, options = {}) {
|
|
|
4864
4942
|
context = counted.context;
|
|
4865
4943
|
const deps = context.deps;
|
|
4866
4944
|
if (!deps) throw new Error("Module rail dependencies are required for composition artifacts");
|
|
4867
|
-
const presentRaw = await listPresentModuleNames(context);
|
|
4945
|
+
const presentRaw = await listPresentModuleNames(context.sandbox);
|
|
4868
4946
|
const presentNames = presentRaw.filter((name) => isValidModuleName(name)).sort((a, b) => a.localeCompare(b));
|
|
4869
4947
|
const moduleFacts = [];
|
|
4870
4948
|
const manifestsByName = {};
|
|
@@ -5084,6 +5162,15 @@ async function reconcileCompositionArtifacts(context, options = {}) {
|
|
|
5084
5162
|
console.log(
|
|
5085
5163
|
`[ModuleRail] runId=${context.runId} composition artifacts writes=${planned.plan.writes.length} deletes=${planned.plan.deletes.length} modules=${registry.modules.length} excluded=${excludedModules.length} changed=${changed} dryRun=${options.dryRun === true} sandboxExecs=${counted.counts.sandboxExecs} sandboxReads=${counted.counts.sandboxReads}`
|
|
5086
5164
|
);
|
|
5165
|
+
if (!options.dryRun && !options.skipComposeInputs) {
|
|
5166
|
+
await writeComposeInputs({
|
|
5167
|
+
db: context.db,
|
|
5168
|
+
projectId: context.projectId,
|
|
5169
|
+
runId: context.runId,
|
|
5170
|
+
sandbox: context.sandbox,
|
|
5171
|
+
deps
|
|
5172
|
+
});
|
|
5173
|
+
}
|
|
5087
5174
|
if (changed && !options.dryRun) {
|
|
5088
5175
|
await applyCompositionArtifactMutations(context, planned.plan, existingFiles);
|
|
5089
5176
|
}
|
|
@@ -5101,26 +5188,7 @@ var HOME_I18N_SUBSTRATE_DIR = `${APP_PACKAGE_DIR}/src/lib/i18n/substrate`;
|
|
|
5101
5188
|
var HOME_I18N_MESSAGES_DIR = `${APP_PACKAGE_DIR}/src/lib/i18n/messages`;
|
|
5102
5189
|
|
|
5103
5190
|
// src/index.ts
|
|
5104
|
-
import { z as z9 } from "zod";
|
|
5105
5191
|
var MODULES_DIR2 = MODULES_SANDBOX_DIR;
|
|
5106
|
-
var COMPOSE_INPUTS_PATH = "apps/web/stardeck.compose.json";
|
|
5107
|
-
var composeInputsSchema = z9.strictObject({
|
|
5108
|
-
connectedStores: z9.array(
|
|
5109
|
-
z9.strictObject({
|
|
5110
|
-
storeId: z9.string().min(1),
|
|
5111
|
-
slug: z9.string().min(1),
|
|
5112
|
-
bindingKey: z9.string().min(1).nullish(),
|
|
5113
|
-
accessLevel: z9.enum(["read", "write", "admin"])
|
|
5114
|
-
})
|
|
5115
|
-
).default([]),
|
|
5116
|
-
installs: z9.record(
|
|
5117
|
-
z9.string(),
|
|
5118
|
-
z9.strictObject({
|
|
5119
|
-
installedVersion: z9.string().min(1),
|
|
5120
|
-
datastoreBindings: z9.record(z9.string(), z9.string()).nullish()
|
|
5121
|
-
})
|
|
5122
|
-
).default({})
|
|
5123
|
-
});
|
|
5124
5192
|
function readComposeInputs(cwd) {
|
|
5125
5193
|
const file = path2.join(cwd, COMPOSE_INPUTS_PATH);
|
|
5126
5194
|
if (!fs2.existsSync(file)) return { connectedStores: [], installs: {} };
|
|
@@ -5154,6 +5222,7 @@ function assertSupportedTypescript(versionMajorMinor) {
|
|
|
5154
5222
|
}
|
|
5155
5223
|
}
|
|
5156
5224
|
var APP_DIR_PREFIX2 = "apps/web/src/app/";
|
|
5225
|
+
var APP_PACKAGE_JSON = "apps/web/package.json";
|
|
5157
5226
|
var STUB_GITIGNORE_PATH = "apps/web/src/app/.gitignore";
|
|
5158
5227
|
var STUB_GITIGNORE_HEADER = "# Generated by stardeck-compose \u2014 Module-rail stubs are build outputs; do not edit or commit them.";
|
|
5159
5228
|
function escapeGitignore(pattern) {
|
|
@@ -5185,10 +5254,10 @@ function assertStubGitignoreOwned(cwd) {
|
|
|
5185
5254
|
}
|
|
5186
5255
|
}
|
|
5187
5256
|
function assertAppRoot(cwd) {
|
|
5188
|
-
const
|
|
5189
|
-
if (!fs2.existsSync(
|
|
5257
|
+
const appPath = path2.join(cwd, APP_PACKAGE_JSON);
|
|
5258
|
+
if (!fs2.existsSync(appPath)) {
|
|
5190
5259
|
throw new Error(
|
|
5191
|
-
`[compose] ${
|
|
5260
|
+
`[compose] ${appPath} not found \u2014 run this from the repo root of a Stardeck app`
|
|
5192
5261
|
);
|
|
5193
5262
|
}
|
|
5194
5263
|
}
|
|
@@ -5292,7 +5361,10 @@ async function compose(options) {
|
|
|
5292
5361
|
assertNoAppLayerImporters(options.cwd, preview.excludedModules);
|
|
5293
5362
|
}
|
|
5294
5363
|
const result = await reconcileCompositionArtifacts(context, {
|
|
5295
|
-
enabledModulesRaw: options.enabled
|
|
5364
|
+
enabledModulesRaw: options.enabled,
|
|
5365
|
+
// compose is the inputs file's reader: the deps above echo it back, so
|
|
5366
|
+
// letting the rail rewrite it would round-trip a fork's own input.
|
|
5367
|
+
skipComposeInputs: true
|
|
5296
5368
|
});
|
|
5297
5369
|
const gitignoreEntries = options.enabled ? null : writeStubGitignore(options.cwd, result.artifactPaths);
|
|
5298
5370
|
let pruned = 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stardeck-customer-apps/compose",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Regenerates a Stardeck app's Module-rail artifacts — the five src/*.gen.ts registries and every route/endpoint stub — from src/modules/*/module.json",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|