effortless-aws 0.1.0 → 0.2.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/index.js CHANGED
@@ -69937,15 +69937,39 @@ var waitForTableActive = (tableName) => Effect_exports.gen(function* () {
69937
69937
  }
69938
69938
  return yield* Effect_exports.fail(new Error(`Timeout waiting for table ${tableName} to become active`));
69939
69939
  });
69940
+ var ensureTimeToLive = (tableName, attributeName) => Effect_exports.gen(function* () {
69941
+ const current = yield* dynamodb_exports.make("describe_time_to_live", {
69942
+ TableName: tableName
69943
+ });
69944
+ const status2 = current.TimeToLiveDescription?.TimeToLiveStatus;
69945
+ const currentAttr = current.TimeToLiveDescription?.AttributeName;
69946
+ if (status2 === "ENABLED" && currentAttr === attributeName) {
69947
+ return;
69948
+ }
69949
+ if (status2 === "ENABLING") {
69950
+ yield* Effect_exports.logInfo(`TTL is being enabled on ${tableName}, waiting...`);
69951
+ yield* Effect_exports.sleep(5e3);
69952
+ return;
69953
+ }
69954
+ yield* Effect_exports.logInfo(`Enabling TTL on ${tableName} (attribute: ${attributeName})`);
69955
+ yield* dynamodb_exports.make("update_time_to_live", {
69956
+ TableName: tableName,
69957
+ TimeToLiveSpecification: {
69958
+ Enabled: true,
69959
+ AttributeName: attributeName
69960
+ }
69961
+ });
69962
+ });
69940
69963
  var ensureTable = (input) => Effect_exports.gen(function* () {
69941
- const { name, pk, sk, billingMode = "PAY_PER_REQUEST", streamView = "NEW_AND_OLD_IMAGES", tags: tags2 } = input;
69964
+ const { name, pk, sk, billingMode = "PAY_PER_REQUEST", streamView = "NEW_AND_OLD_IMAGES", tags: tags2, ttlAttribute } = input;
69942
69965
  const existingTable = yield* dynamodb_exports.make("describe_table", { TableName: name }).pipe(
69943
- Effect_exports.map((result) => result.Table),
69966
+ Effect_exports.map((result2) => result2.Table),
69944
69967
  Effect_exports.catchIf(
69945
69968
  (error4) => error4 instanceof dynamodb_exports.DynamoDBError && error4.cause.name === "ResourceNotFoundException",
69946
69969
  () => Effect_exports.succeed(void 0)
69947
69970
  )
69948
69971
  );
69972
+ let result;
69949
69973
  if (!existingTable) {
69950
69974
  yield* Effect_exports.logInfo(`Creating table ${name}...`);
69951
69975
  const keySchema = [
@@ -69967,34 +69991,40 @@ var ensureTable = (input) => Effect_exports.gen(function* () {
69967
69991
  Tags: tags2 ? toAwsTagList(tags2) : void 0
69968
69992
  });
69969
69993
  const table3 = yield* waitForTableActive(name);
69970
- return {
69994
+ result = {
69971
69995
  tableArn: table3.TableArn,
69972
69996
  streamArn: table3.LatestStreamArn
69973
69997
  };
69998
+ } else {
69999
+ yield* Effect_exports.logInfo(`Table ${name} already exists`);
70000
+ if (tags2) {
70001
+ yield* dynamodb_exports.make("tag_resource", {
70002
+ ResourceArn: existingTable.TableArn,
70003
+ Tags: toAwsTagList(tags2)
70004
+ });
70005
+ }
70006
+ if (!existingTable.StreamSpecification?.StreamEnabled) {
70007
+ yield* Effect_exports.logInfo(`Enabling stream on table ${name}...`);
70008
+ yield* dynamodb_exports.make("update_table", {
70009
+ TableName: name,
70010
+ StreamSpecification: streamViewToSpec(streamView)
70011
+ });
70012
+ const table3 = yield* waitForTableActive(name);
70013
+ result = {
70014
+ tableArn: table3.TableArn,
70015
+ streamArn: table3.LatestStreamArn
70016
+ };
70017
+ } else {
70018
+ result = {
70019
+ tableArn: existingTable.TableArn,
70020
+ streamArn: existingTable.LatestStreamArn
70021
+ };
70022
+ }
69974
70023
  }
69975
- yield* Effect_exports.logInfo(`Table ${name} already exists`);
69976
- if (tags2) {
69977
- yield* dynamodb_exports.make("tag_resource", {
69978
- ResourceArn: existingTable.TableArn,
69979
- Tags: toAwsTagList(tags2)
69980
- });
69981
- }
69982
- if (!existingTable.StreamSpecification?.StreamEnabled) {
69983
- yield* Effect_exports.logInfo(`Enabling stream on table ${name}...`);
69984
- yield* dynamodb_exports.make("update_table", {
69985
- TableName: name,
69986
- StreamSpecification: streamViewToSpec(streamView)
69987
- });
69988
- const table3 = yield* waitForTableActive(name);
69989
- return {
69990
- tableArn: table3.TableArn,
69991
- streamArn: table3.LatestStreamArn
69992
- };
70024
+ if (ttlAttribute) {
70025
+ yield* ensureTimeToLive(name, ttlAttribute);
69993
70026
  }
69994
- return {
69995
- tableArn: existingTable.TableArn,
69996
- streamArn: existingTable.LatestStreamArn
69997
- };
70027
+ return result;
69998
70028
  });
69999
70029
  var ensureEventSourceMapping = (input) => Effect_exports.gen(function* () {
70000
70030
  const { functionArn, streamArn, batchSize = 100, batchWindow, startingPosition = "LATEST" } = input;
@@ -70146,7 +70176,6 @@ import * as fs from "fs/promises";
70146
70176
  import * as fsSync from "fs";
70147
70177
  import * as path4 from "path";
70148
70178
  import archiver from "archiver";
70149
- import { nodeFileTrace } from "@vercel/nft";
70150
70179
  var FIXED_DATE = /* @__PURE__ */ new Date(0);
70151
70180
  var getPackageVersion = (pkgPath) => {
70152
70181
  const pkgJsonPath = path4.join(pkgPath, "package.json");
@@ -70163,10 +70192,10 @@ var computeLockfileHash = (projectDir) => Effect_exports.gen(function* () {
70163
70192
  if (prodDeps.length === 0) {
70164
70193
  return yield* Effect_exports.fail(new Error("No production dependencies"));
70165
70194
  }
70166
- const allPackages = collectTransitiveDeps(projectDir, prodDeps);
70195
+ const { packages: allPackages, resolvedPaths } = collectTransitiveDeps(projectDir, prodDeps);
70167
70196
  const packageVersions = [];
70168
70197
  for (const pkgName of Array.from(allPackages).sort()) {
70169
- const pkgPath = findInPnpmStore(projectDir, pkgName) ?? getPackageRealPath(projectDir, pkgName);
70198
+ const pkgPath = resolvedPaths.get(pkgName) ?? findInPnpmStore(projectDir, pkgName) ?? getPackageRealPath(projectDir, pkgName);
70170
70199
  if (pkgPath) {
70171
70200
  const version = getPackageVersion(pkgPath);
70172
70201
  if (version) {
@@ -70189,20 +70218,6 @@ var readProductionDependencies = (projectDir) => Effect_exports.gen(function* ()
70189
70218
  const pkg = JSON.parse(content);
70190
70219
  return Object.keys(pkg.dependencies ?? {});
70191
70220
  });
70192
- var extractPackageName = (filePath) => {
70193
- const nodeModulesIndex = filePath.lastIndexOf("node_modules");
70194
- if (nodeModulesIndex === -1) return null;
70195
- const afterNodeModules = filePath.slice(nodeModulesIndex + "node_modules/".length);
70196
- const parts2 = afterNodeModules.split("/");
70197
- const firstPart = parts2[0];
70198
- if (!firstPart) return null;
70199
- if (firstPart.startsWith("@") && parts2.length >= 2) {
70200
- const secondPart = parts2[1];
70201
- if (!secondPart) return null;
70202
- return `${firstPart}/${secondPart}`;
70203
- }
70204
- return firstPart;
70205
- };
70206
70221
  var getPackageRealPath = (projectDir, pkgName) => {
70207
70222
  const pkgPath = path4.join(projectDir, "node_modules", pkgName);
70208
70223
  if (!fsSync.existsSync(pkgPath)) return null;
@@ -70212,33 +70227,6 @@ var getPackageRealPath = (projectDir, pkgName) => {
70212
70227
  return null;
70213
70228
  }
70214
70229
  };
70215
- var findPackageEntryPoint = (depPath) => {
70216
- const pkgJsonPath = path4.join(depPath, "package.json");
70217
- if (!fsSync.existsSync(pkgJsonPath)) return null;
70218
- try {
70219
- const pkgJson = JSON.parse(fsSync.readFileSync(pkgJsonPath, "utf-8"));
70220
- const candidates = [
70221
- pkgJson.main,
70222
- pkgJson.module,
70223
- pkgJson.exports?.["."]?.require,
70224
- pkgJson.exports?.["."]?.import,
70225
- pkgJson.exports?.["."]?.default,
70226
- typeof pkgJson.exports === "string" ? pkgJson.exports : null,
70227
- "index.js",
70228
- "index.cjs",
70229
- "index.mjs"
70230
- ].filter(Boolean);
70231
- for (const candidate of candidates) {
70232
- const entryPath = path4.join(depPath, candidate);
70233
- if (fsSync.existsSync(entryPath) && fsSync.statSync(entryPath).isFile()) {
70234
- return entryPath;
70235
- }
70236
- }
70237
- return null;
70238
- } catch {
70239
- return null;
70240
- }
70241
- };
70242
70230
  var getPackageDeps = (pkgPath) => {
70243
70231
  const pkgJsonPath = path4.join(pkgPath, "package.json");
70244
70232
  if (!fsSync.existsSync(pkgJsonPath)) return [];
@@ -70273,7 +70261,7 @@ var findInPnpmStore = (projectDir, pkgName) => {
70273
70261
  }
70274
70262
  return null;
70275
70263
  };
70276
- var collectTransitiveDeps = (projectDir, rootDeps, searchPath = path4.join(projectDir, "node_modules"), visited = /* @__PURE__ */ new Set()) => {
70264
+ var collectTransitiveDeps = (projectDir, rootDeps, searchPath = path4.join(projectDir, "node_modules"), visited = /* @__PURE__ */ new Set(), resolvedPaths = /* @__PURE__ */ new Map(), warnings = []) => {
70277
70265
  const rootNodeModules = path4.join(projectDir, "node_modules");
70278
70266
  for (const dep of rootDeps) {
70279
70267
  if (visited.has(dep)) continue;
@@ -70282,7 +70270,8 @@ var collectTransitiveDeps = (projectDir, rootDeps, searchPath = path4.join(proje
70282
70270
  if (fsSync.existsSync(pkgPath)) {
70283
70271
  try {
70284
70272
  realPath2 = fsSync.realpathSync(pkgPath);
70285
- } catch {
70273
+ } catch (err) {
70274
+ warnings.push(`realpathSync failed for "${dep}" at ${pkgPath}: ${err instanceof Error ? err.message : String(err)}`);
70286
70275
  }
70287
70276
  }
70288
70277
  if (!realPath2 && searchPath !== rootNodeModules) {
@@ -70290,59 +70279,76 @@ var collectTransitiveDeps = (projectDir, rootDeps, searchPath = path4.join(proje
70290
70279
  if (fsSync.existsSync(pkgPath)) {
70291
70280
  try {
70292
70281
  realPath2 = fsSync.realpathSync(pkgPath);
70293
- } catch {
70282
+ } catch (err) {
70283
+ warnings.push(`realpathSync failed for "${dep}" at ${pkgPath}: ${err instanceof Error ? err.message : String(err)}`);
70294
70284
  }
70295
70285
  }
70296
70286
  }
70297
70287
  if (!realPath2) {
70298
70288
  realPath2 = findInPnpmStore(projectDir, dep);
70299
70289
  }
70300
- if (!realPath2) continue;
70290
+ if (!realPath2) {
70291
+ warnings.push(`Package "${dep}" not found (searched: ${searchPath}, root node_modules, pnpm store) \u2014 entire subtree skipped`);
70292
+ continue;
70293
+ }
70301
70294
  visited.add(dep);
70295
+ resolvedPaths.set(dep, realPath2);
70302
70296
  const pkgDeps = getPackageDeps(realPath2);
70303
70297
  if (pkgDeps.length > 0) {
70304
70298
  const isScoped = dep.startsWith("@");
70305
70299
  const pkgNodeModules = isScoped ? path4.dirname(path4.dirname(realPath2)) : path4.dirname(realPath2);
70306
- collectTransitiveDeps(projectDir, pkgDeps, pkgNodeModules, visited);
70307
- }
70308
- }
70309
- return visited;
70310
- };
70311
- var collectLayerPackages = async (projectDir, dependencies) => {
70312
- if (dependencies.length === 0) return [];
70313
- const packages = collectTransitiveDeps(projectDir, dependencies);
70314
- const entryPoints = [];
70315
- for (const dep of dependencies) {
70316
- const pkgPath = path4.join(projectDir, "node_modules", dep);
70317
- if (fsSync.existsSync(pkgPath)) {
70318
- const entryPoint = findPackageEntryPoint(pkgPath);
70319
- if (entryPoint) {
70320
- entryPoints.push(entryPoint);
70321
- }
70322
- }
70323
- }
70324
- if (entryPoints.length > 0) {
70325
- try {
70326
- const { fileList } = await nodeFileTrace(entryPoints, {
70327
- base: projectDir
70328
- });
70329
- for (const file6 of fileList) {
70330
- const pkgName = extractPackageName(path4.join(projectDir, file6));
70331
- if (pkgName) {
70332
- packages.add(pkgName);
70300
+ collectTransitiveDeps(projectDir, pkgDeps, pkgNodeModules, visited, resolvedPaths, warnings);
70301
+ }
70302
+ }
70303
+ return { packages: visited, resolvedPaths, warnings };
70304
+ };
70305
+ var isAwsRuntime = (pkg) => pkg.startsWith("@aws-sdk/") || pkg.startsWith("@smithy/");
70306
+ var collectLayerPackages = (projectDir, dependencies) => {
70307
+ if (dependencies.length === 0) return { packages: [], resolvedPaths: /* @__PURE__ */ new Map(), warnings: [] };
70308
+ const { packages, resolvedPaths, warnings } = collectTransitiveDeps(projectDir, dependencies);
70309
+ let changed = true;
70310
+ while (changed) {
70311
+ changed = false;
70312
+ for (const pkg of [...packages]) {
70313
+ if (isAwsRuntime(pkg)) continue;
70314
+ const pkgPaths = /* @__PURE__ */ new Set();
70315
+ const resolved = resolvedPaths.get(pkg);
70316
+ if (resolved) pkgPaths.add(resolved);
70317
+ const found = findPackagePath(projectDir, pkg);
70318
+ if (found) pkgPaths.add(found);
70319
+ if (pkgPaths.size === 0) continue;
70320
+ for (const pkgPath of pkgPaths) {
70321
+ const pkgDeps = getPackageDeps(pkgPath);
70322
+ for (const dep of pkgDeps) {
70323
+ if (!packages.has(dep) && !isAwsRuntime(dep)) {
70324
+ packages.add(dep);
70325
+ changed = true;
70326
+ let depPath = findPackagePath(projectDir, dep);
70327
+ if (!depPath) {
70328
+ const isScoped = pkg.startsWith("@");
70329
+ const parentNodeModules = isScoped ? path4.dirname(path4.dirname(pkgPath)) : path4.dirname(pkgPath);
70330
+ const depInParent = path4.join(parentNodeModules, dep);
70331
+ if (fsSync.existsSync(depInParent)) {
70332
+ try {
70333
+ depPath = fsSync.realpathSync(depInParent);
70334
+ } catch {
70335
+ }
70336
+ }
70337
+ }
70338
+ if (depPath) resolvedPaths.set(dep, depPath);
70339
+ }
70333
70340
  }
70334
70341
  }
70335
- } catch {
70336
70342
  }
70337
70343
  }
70338
- return Array.from(packages);
70344
+ return { packages: Array.from(packages), resolvedPaths, warnings };
70339
70345
  };
70340
70346
  var findPackagePath = (projectDir, pkgName) => {
70341
70347
  const rootPath = getPackageRealPath(projectDir, pkgName);
70342
70348
  if (rootPath) return rootPath;
70343
70349
  return findInPnpmStore(projectDir, pkgName);
70344
70350
  };
70345
- var createLayerZip = (projectDir, packages) => Effect_exports.async((resume2) => {
70351
+ var createLayerZip = (projectDir, packages, resolvedPaths) => Effect_exports.async((resume2) => {
70346
70352
  const chunks2 = [];
70347
70353
  const archive = archiver("zip", { zlib: { level: 9 } });
70348
70354
  const addedPaths = /* @__PURE__ */ new Set();
@@ -70356,7 +70362,7 @@ var createLayerZip = (projectDir, packages) => Effect_exports.async((resume2) =>
70356
70362
  })));
70357
70363
  archive.on("error", (err) => resume2(Effect_exports.fail(err)));
70358
70364
  for (const pkgName of packages) {
70359
- const realPath2 = findPackagePath(projectDir, pkgName);
70365
+ const realPath2 = resolvedPaths?.get(pkgName) ?? findPackagePath(projectDir, pkgName);
70360
70366
  if (typeof realPath2 === "string" && realPath2.length > 0 && !addedPaths.has(realPath2)) {
70361
70367
  addedPaths.add(realPath2);
70362
70368
  includedPackages.push(pkgName);
@@ -70414,10 +70420,13 @@ var ensureLayer = (config2) => Effect_exports.gen(function* () {
70414
70420
  yield* Effect_exports.logInfo(`Layer ${layerName} with hash ${hash2} already exists (version ${existing.version})`);
70415
70421
  return existing;
70416
70422
  }
70417
- const allPackages = yield* Effect_exports.promise(() => collectLayerPackages(config2.projectDir, dependencies));
70423
+ const { packages: allPackages, resolvedPaths, warnings: layerWarnings } = yield* Effect_exports.sync(() => collectLayerPackages(config2.projectDir, dependencies));
70424
+ for (const warning of layerWarnings) {
70425
+ yield* Effect_exports.logWarning(`[layer] ${warning}`);
70426
+ }
70418
70427
  yield* Effect_exports.logInfo(`Creating layer ${layerName} with ${allPackages.length} packages (hash: ${hash2})`);
70419
70428
  yield* Effect_exports.logDebug(`Layer packages: ${allPackages.join(", ")}`);
70420
- const { buffer: layerZip, includedPackages, skippedPackages } = yield* createLayerZip(config2.projectDir, allPackages);
70429
+ const { buffer: layerZip, includedPackages, skippedPackages } = yield* createLayerZip(config2.projectDir, allPackages, resolvedPaths);
70421
70430
  if (skippedPackages.length > 0) {
70422
70431
  yield* Effect_exports.logWarning(`Skipped ${skippedPackages.length} packages (not found): ${skippedPackages.slice(0, 10).join(", ")}${skippedPackages.length > 10 ? "..." : ""}`);
70423
70432
  }
@@ -70720,7 +70729,10 @@ var ensureLayerAndExternal = (input) => Effect_exports.gen(function* () {
70720
70729
  projectDir: input.projectDir
70721
70730
  });
70722
70731
  const prodDeps = layerResult ? yield* readProductionDependencies(input.projectDir) : [];
70723
- const external = prodDeps.length > 0 ? yield* Effect_exports.promise(() => collectLayerPackages(input.projectDir, prodDeps)) : [];
70732
+ const { packages: external, warnings: layerWarnings } = prodDeps.length > 0 ? yield* Effect_exports.sync(() => collectLayerPackages(input.projectDir, prodDeps)) : { packages: [], warnings: [] };
70733
+ for (const warning of layerWarnings) {
70734
+ yield* Effect_exports.logWarning(`[layer] ${warning}`);
70735
+ }
70724
70736
  return {
70725
70737
  layerArn: layerResult?.layerVersionArn,
70726
70738
  external
@@ -71056,7 +71068,10 @@ var prepareLayer = (input) => Effect_exports.gen(function* () {
71056
71068
  )
71057
71069
  );
71058
71070
  const prodDeps = layerResult ? yield* readProductionDependencies(input.projectDir) : [];
71059
- const external = prodDeps.length > 0 ? yield* Effect_exports.promise(() => collectLayerPackages(input.projectDir, prodDeps)) : [];
71071
+ const { packages: external, warnings: layerWarnings } = prodDeps.length > 0 ? yield* Effect_exports.sync(() => collectLayerPackages(input.projectDir, prodDeps)) : { packages: [], warnings: [] };
71072
+ for (const warning of layerWarnings) {
71073
+ yield* Effect_exports.logWarning(`[layer] ${warning}`);
71074
+ }
71060
71075
  yield* Effect_exports.logDebug(`Layer result: ${layerResult ? "exists" : "null"}, external packages: ${external.length}`);
71061
71076
  if (external.length > 0) {
71062
71077
  yield* Effect_exports.logInfo(`Bundling with ${external.length} external packages from layer`);
@@ -71117,6 +71132,31 @@ var mergeResolved = (deps, params) => {
71117
71132
  if (Object.keys(env2).length === 0) return void 0;
71118
71133
  return { depsEnv: env2, depsPermissions: permissions };
71119
71134
  };
71135
+ var PLATFORM_PERMISSIONS = [
71136
+ "dynamodb:PutItem",
71137
+ "dynamodb:GetItem",
71138
+ "dynamodb:UpdateItem",
71139
+ "dynamodb:Query"
71140
+ ];
71141
+ var ensurePlatformTable = (project2, stage, region) => Effect_exports.gen(function* () {
71142
+ const tableName = `${project2}-${stage}-platform`;
71143
+ const tagCtx = { project: project2, stage, handler: "platform" };
71144
+ yield* Effect_exports.logInfo(`Ensuring platform table: ${tableName}`);
71145
+ yield* ensureTable({
71146
+ name: tableName,
71147
+ pk: { name: "pk", type: "string" },
71148
+ sk: { name: "sk", type: "string" },
71149
+ billingMode: "PAY_PER_REQUEST",
71150
+ streamView: "NEW_AND_OLD_IMAGES",
71151
+ tags: makeTags(tagCtx, "dynamodb"),
71152
+ ttlAttribute: "ttl"
71153
+ }).pipe(
71154
+ Effect_exports.provide(
71155
+ clients_exports.makeClients({ dynamodb: { region } })
71156
+ )
71157
+ );
71158
+ return tableName;
71159
+ });
71120
71160
  var deployHttpHandlers = (ctx) => Effect_exports.gen(function* () {
71121
71161
  const results = [];
71122
71162
  for (const { file: file6, exports } of ctx.handlers) {
@@ -71134,12 +71174,17 @@ var deployHttpHandlers = (ctx) => Effect_exports.gen(function* () {
71134
71174
  resolveDeps(fn2.depsKeys, ctx.tableNameMap),
71135
71175
  resolveParams(fn2.paramEntries, ctx.input.project, stage)
71136
71176
  );
71177
+ const withPlatform = {
71178
+ depsEnv: { ...resolved?.depsEnv, ...ctx.platformEnv },
71179
+ depsPermissions: [...resolved?.depsPermissions ?? [], ...ctx.platformPermissions]
71180
+ };
71137
71181
  const { exportName, functionArn, config: config2 } = yield* deployLambda({
71138
71182
  input: deployInput,
71139
71183
  fn: fn2,
71140
71184
  ...ctx.layerArn ? { layerArn: ctx.layerArn } : {},
71141
71185
  ...ctx.external.length > 0 ? { external: ctx.external } : {},
71142
- ...resolved ? { depsEnv: resolved.depsEnv, depsPermissions: resolved.depsPermissions } : {}
71186
+ depsEnv: withPlatform.depsEnv,
71187
+ depsPermissions: withPlatform.depsPermissions
71143
71188
  }).pipe(
71144
71189
  Effect_exports.provide(
71145
71190
  clients_exports.makeClients({
@@ -71185,12 +71230,17 @@ var deployTableHandlers = (ctx) => Effect_exports.gen(function* () {
71185
71230
  resolveDeps(fn2.depsKeys, ctx.tableNameMap),
71186
71231
  resolveParams(fn2.paramEntries, ctx.input.project, stage)
71187
71232
  );
71233
+ const withPlatform = {
71234
+ depsEnv: { ...resolved?.depsEnv, ...ctx.platformEnv },
71235
+ depsPermissions: [...resolved?.depsPermissions ?? [], ...ctx.platformPermissions]
71236
+ };
71188
71237
  const result = yield* deployTableFunction({
71189
71238
  input: deployInput,
71190
71239
  fn: fn2,
71191
71240
  ...ctx.layerArn ? { layerArn: ctx.layerArn } : {},
71192
71241
  ...ctx.external.length > 0 ? { external: ctx.external } : {},
71193
- ...resolved ? { depsEnv: resolved.depsEnv, depsPermissions: resolved.depsPermissions } : {}
71242
+ depsEnv: withPlatform.depsEnv,
71243
+ depsPermissions: withPlatform.depsPermissions
71194
71244
  }).pipe(
71195
71245
  Effect_exports.provide(
71196
71246
  clients_exports.makeClients({
@@ -71225,6 +71275,9 @@ var deployProject = (input) => Effect_exports.gen(function* () {
71225
71275
  region: input.region,
71226
71276
  projectDir: input.projectDir
71227
71277
  });
71278
+ const stage = resolveStage(input.stage);
71279
+ const platformTableName = yield* ensurePlatformTable(input.project, stage, input.region);
71280
+ const platformEnv = { EFF_PLATFORM_TABLE: platformTableName };
71228
71281
  let apiId;
71229
71282
  let apiUrl;
71230
71283
  if (totalHttpHandlers > 0) {
@@ -71255,14 +71308,18 @@ var deployProject = (input) => Effect_exports.gen(function* () {
71255
71308
  input,
71256
71309
  layerArn,
71257
71310
  external,
71258
- tableNameMap
71311
+ tableNameMap,
71312
+ platformEnv,
71313
+ platformPermissions: PLATFORM_PERMISSIONS
71259
71314
  }) : [];
71260
71315
  const tableResults = yield* deployTableHandlers({
71261
71316
  handlers: tableHandlers,
71262
71317
  input,
71263
71318
  layerArn,
71264
71319
  external,
71265
- tableNameMap
71320
+ tableNameMap,
71321
+ platformEnv,
71322
+ platformPermissions: PLATFORM_PERMISSIONS
71266
71323
  });
71267
71324
  if (apiUrl) {
71268
71325
  yield* Effect_exports.logInfo(`Deployment complete! API: ${apiUrl}`);
@@ -71539,7 +71596,10 @@ var buildCommand = Command_exports.make(
71539
71596
  const prodDeps = yield* readProductionDependencies(projectDir).pipe(
71540
71597
  Effect_exports.catchAll(() => Effect_exports.succeed([]))
71541
71598
  );
71542
- const external = prodDeps.length > 0 ? yield* Effect_exports.promise(() => collectLayerPackages(projectDir, prodDeps)) : [];
71599
+ const { packages: external, warnings: layerWarnings } = prodDeps.length > 0 ? yield* Effect_exports.sync(() => collectLayerPackages(projectDir, prodDeps)) : { packages: [], warnings: [] };
71600
+ for (const warning of layerWarnings) {
71601
+ yield* Effect_exports.logWarning(`[layer] ${warning}`);
71602
+ }
71543
71603
  if (external.length > 0) {
71544
71604
  yield* Console_exports.log(`Using ${external.length} external packages (from layer)
71545
71605
  `);
@@ -72055,7 +72115,14 @@ Lockfile hash: ${hash2}`);
72055
72115
  } else {
72056
72116
  yield* Console_exports.log("\nNo lockfile found (package-lock.json, pnpm-lock.yaml, or yarn.lock)");
72057
72117
  }
72058
- const allPackages = yield* Effect_exports.promise(() => collectLayerPackages(projectDir, prodDeps));
72118
+ const { packages: allPackages, warnings: layerWarnings } = yield* Effect_exports.sync(() => collectLayerPackages(projectDir, prodDeps));
72119
+ if (layerWarnings.length > 0) {
72120
+ yield* Console_exports.log(`
72121
+ Warnings (${layerWarnings.length}):`);
72122
+ for (const w of layerWarnings) {
72123
+ yield* Console_exports.log(` \u26A0 ${w}`);
72124
+ }
72125
+ }
72059
72126
  yield* Console_exports.log(`
72060
72127
  Total packages for layer (${allPackages.length}):`);
72061
72128
  if (verbose) {
@@ -72129,31 +72196,6 @@ Deleted ${deleted} layer version(s).`);
72129
72196
  );
72130
72197
  })
72131
72198
  ).pipe(Command_exports.withDescription("Delete layer versions"));
72132
- var findPackagePathForCopy = (projectDir, pkgName) => {
72133
- const rootPath = path11.join(projectDir, "node_modules", pkgName);
72134
- if (fs5.existsSync(rootPath)) {
72135
- try {
72136
- return fs5.realpathSync(rootPath);
72137
- } catch {
72138
- }
72139
- }
72140
- const pnpmDir = path11.join(projectDir, "node_modules", ".pnpm");
72141
- if (!fs5.existsSync(pnpmDir)) return null;
72142
- const pnpmPkgName = pkgName.replace("/", "+");
72143
- try {
72144
- const entries2 = fs5.readdirSync(pnpmDir);
72145
- for (const entry of entries2) {
72146
- if (entry.startsWith(pnpmPkgName + "@")) {
72147
- const pkgPath = path11.join(pnpmDir, entry, "node_modules", pkgName);
72148
- if (fs5.existsSync(pkgPath)) {
72149
- return fs5.realpathSync(pkgPath);
72150
- }
72151
- }
72152
- }
72153
- } catch {
72154
- }
72155
- return null;
72156
- };
72157
72199
  var layersBuildCommand = Command_exports.make(
72158
72200
  "build",
72159
72201
  { output: outputOption, verbose: verboseOption },
@@ -72184,7 +72226,14 @@ var layersBuildCommand = Command_exports.make(
72184
72226
  );
72185
72227
  yield* Console_exports.log(`
72186
72228
  Lockfile hash: ${hash2}`);
72187
- const allPackages = yield* Effect_exports.promise(() => collectLayerPackages(projectDir, prodDeps));
72229
+ const { packages: allPackages, resolvedPaths, warnings: layerWarnings } = yield* Effect_exports.sync(() => collectLayerPackages(projectDir, prodDeps));
72230
+ if (layerWarnings.length > 0) {
72231
+ yield* Console_exports.log(`
72232
+ Warnings (${layerWarnings.length}):`);
72233
+ for (const w of layerWarnings) {
72234
+ yield* Console_exports.log(` \u26A0 ${w}`);
72235
+ }
72236
+ }
72188
72237
  yield* Console_exports.log(`
72189
72238
  Collected ${allPackages.length} packages for layer`);
72190
72239
  if (verbose) {
@@ -72196,7 +72245,7 @@ Collected ${allPackages.length} packages for layer`);
72196
72245
  let copied = 0;
72197
72246
  let skipped = 0;
72198
72247
  for (const pkgName of allPackages) {
72199
- const srcPath = findPackagePathForCopy(projectDir, pkgName);
72248
+ const srcPath = resolvedPaths.get(pkgName) ?? null;
72200
72249
  if (!srcPath) {
72201
72250
  skipped++;
72202
72251
  if (verbose) {