@awsless/awsless 0.0.579 → 0.0.581

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/bin.js CHANGED
@@ -1,7 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- shortId
4
- } from "./chunk-W4ED7XCC.js";
5
2
 
6
3
  // src/cli/program.ts
7
4
  import { Command } from "commander";
@@ -874,6 +871,10 @@ var FileCodeSchema = z14.object({
874
871
  });
875
872
  var BundleCodeSchema = z14.object({
876
873
  bundle: LocalDirectorySchema.describe("The directory that needs to be bundled.")
874
+ // dir: z.string(),
875
+ // build: z.string(),
876
+ // run: z.string(),
877
+ // cacheKey:
877
878
  });
878
879
  var CodeSchema = z14.union([
879
880
  LocalFileSchema.transform((file) => ({
@@ -3105,6 +3106,12 @@ var listAllFiles = async (list3) => {
3105
3106
  return files;
3106
3107
  };
3107
3108
 
3109
+ // src/util/id.ts
3110
+ import { createHash as createHash3 } from "crypto";
3111
+ var shortId = (ns) => {
3112
+ return createHash3("md5").update(ns).digest("hex").substring(0, 10);
3113
+ };
3114
+
3108
3115
  // src/util/temp.ts
3109
3116
  import { mkdir as mkdir3, readdir as readdir2, rm as rm2 } from "fs/promises";
3110
3117
  import { join as join8 } from "path";
@@ -3963,7 +3970,7 @@ var onFailureFeature = defineFeature({
3963
3970
  }
3964
3971
  });
3965
3972
 
3966
- // src/feature/pubsub/appsync/index.ts
3973
+ // src/feature/pubsub/index.ts
3967
3974
  import { $ as $9, Group as Group9 } from "@awsless/formation";
3968
3975
  import { constantCase as constantCase5 } from "change-case";
3969
3976
 
@@ -3985,141 +3992,90 @@ var formatFullDomainName = (config2, id, subDomain) => {
3985
3992
  return domain2;
3986
3993
  };
3987
3994
 
3988
- // src/feature/pubsub/appsync/index.ts
3995
+ // src/feature/pubsub/index.ts
3989
3996
  var pubsubFeature = defineFeature({
3990
3997
  name: "pubsub",
3991
3998
  onApp(ctx) {
3992
- for (const [id, props] of Object.entries(ctx.appConfig.defaults?.pubsub ?? {})) {
3999
+ ctx.addGlobalPermission({
4000
+ actions: ["iot:Publish"],
4001
+ resources: [
4002
+ // `arn:aws:iot:${ctx.appConfig.region}:${ctx.accountId}:topic/*`,
4003
+ `arn:aws:iot:${ctx.appConfig.region}:${ctx.accountId}:topic/${ctx.app.name}/pubsub/*`
4004
+ ]
4005
+ });
4006
+ for (const [id, props] of Object.entries(ctx.appConfig.defaults.pubsub ?? {})) {
3993
4007
  const group = new Group9(ctx.base, "pubsub", id);
3994
- const shortName = `${ctx.app.name}--${id}`;
4008
+ const { lambda } = createLambdaFunction(group, ctx, "pubsub-authorizer", id, props.auth);
3995
4009
  const name = formatGlobalResourceName({
3996
4010
  appName: ctx.app.name,
3997
4011
  resourceType: "pubsub",
3998
4012
  resourceName: id
3999
4013
  });
4000
- const authGroup = new Group9(group, "auth", "lambda");
4001
- const { lambda: authLambda } = createLambdaFunction(authGroup, ctx, "pubsub", `${id}-auth`, {
4002
- ...props.auth,
4003
- description: `PubSub ${id} authorizer`
4004
- });
4005
- let loggingRole;
4006
- if (props.logLevel) {
4007
- loggingRole = new $9.aws.iam.Role(group, "logging-role", {
4008
- name: shortId(`${name}-logging-role`),
4009
- assumeRolePolicy: JSON.stringify({
4010
- Version: "2012-10-17",
4011
- Statement: [
4012
- {
4013
- Effect: "Allow",
4014
- Principal: {
4015
- Service: "appsync.amazonaws.com"
4016
- },
4017
- Action: "sts:AssumeRole"
4018
- }
4019
- ]
4020
- })
4021
- });
4022
- new $9.aws.iam.RolePolicyAttachment(group, "logs-policy", {
4023
- role: loggingRole.name,
4024
- policyArn: "arn:aws:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs"
4025
- });
4026
- }
4027
- const api = new $9.aws.appsync.Api(group, "api", {
4028
- name: shortName,
4029
- eventConfig: [
4030
- {
4031
- connectionAuthMode: [{ authType: "AWS_IAM" }, { authType: "AWS_LAMBDA" }],
4032
- authProvider: [
4033
- {
4034
- authType: "AWS_LAMBDA",
4035
- lambdaAuthorizerConfig: [
4036
- {
4037
- authorizerUri: authLambda.arn,
4038
- authorizerResultTtlInSeconds: 300
4039
- }
4040
- ]
4041
- },
4042
- {
4043
- authType: "AWS_IAM"
4044
- }
4045
- ],
4046
- defaultPublishAuthMode: [
4047
- {
4048
- authType: "AWS_IAM"
4049
- }
4050
- ],
4051
- defaultSubscribeAuthMode: [
4052
- {
4053
- authType: "AWS_LAMBDA"
4054
- },
4055
- {
4056
- authType: "AWS_IAM"
4057
- }
4058
- ],
4059
- logConfig: props.logLevel ? [
4060
- {
4061
- logLevel: props.logLevel.toUpperCase(),
4062
- cloudwatchLogsRoleArn: loggingRole.arn
4063
- }
4064
- ] : void 0
4065
- }
4066
- ]
4014
+ const authorizer = new $9.aws.iot.Authorizer(group, "authorizer", {
4015
+ name,
4016
+ authorizerFunctionArn: lambda.arn,
4017
+ status: "ACTIVE",
4018
+ signingDisabled: true,
4019
+ enableCachingForHttp: false
4067
4020
  });
4068
- const namespaces = props.namespaces ?? ["default"];
4069
- for (const namespace of namespaces) {
4070
- new $9.aws.appsync.ChannelNamespace(group, `namespace-${namespace}`, {
4071
- name: namespace,
4072
- apiId: api.apiId
4073
- });
4074
- }
4075
- new $9.aws.lambda.Permission(group, "auth-permission", {
4021
+ new $9.aws.lambda.Permission(group, "permission", {
4022
+ functionName: lambda.functionName,
4076
4023
  action: "lambda:InvokeFunction",
4077
- principal: "appsync.amazonaws.com",
4078
- functionName: authLambda.functionName,
4079
- sourceArn: api.apiArn
4024
+ principal: "iot.amazonaws.com",
4025
+ sourceArn: authorizer.arn
4026
+ });
4027
+ ctx.bind(`PUBSUB_${constantCase5(id)}_AUTHORIZER`, name);
4028
+ const endpoint = $9.aws.iot.getEndpoint(group, "endpoint", {
4029
+ endpointType: "iot:Data-ATS"
4080
4030
  });
4081
4031
  if (props.domain) {
4082
4032
  const domainName = formatFullDomainName(ctx.appConfig, props.domain, props.subDomain);
4083
- const zoneId = ctx.shared.entry("domain", `zone-id`, props.domain);
4084
- const certificateArn = ctx.shared.entry("domain", `certificate-arn`, props.domain);
4085
- const apiDomain = new $9.aws.appsync.DomainName(group, "domain", {
4033
+ new $9.aws.iot.DomainConfiguration(group, "domain", {
4034
+ name,
4086
4035
  domainName,
4087
- certificateArn
4088
- });
4089
- new $9.aws.appsync.DomainNameApiAssociation(group, "domain-association", {
4090
- apiId: api.apiArn,
4091
- domainName: apiDomain.domainName
4036
+ serverCertificateArns: [ctx.shared.entry("domain", `certificate-arn`, props.domain)],
4037
+ authorizerConfig: {
4038
+ defaultAuthorizerName: authorizer.name
4039
+ }
4040
+ // validationCertificate: ctx.shared.get(`global-certificate-${props.domain}-arn`),
4092
4041
  });
4093
4042
  new $9.aws.route53.Record(group, "record", {
4094
- zoneId,
4095
- type: "CNAME",
4043
+ zoneId: ctx.shared.entry("domain", `zone-id`, props.domain),
4096
4044
  name: domainName,
4097
- records: [apiDomain.appsyncDomainName],
4098
- ttl: 300
4045
+ type: "CNAME",
4046
+ records: [endpoint.endpointAddress]
4099
4047
  });
4100
- ctx.bind(`PUBSUB_${constantCase5(id)}_ENDPOINT`, `${domainName}/event`);
4101
- ctx.bind(`PUBSUB_${constantCase5(id)}_REALTIME_ENDPOINT`, `${domainName}/event/realtime`);
4048
+ ctx.bind(`PUBSUB_${constantCase5(id)}_ENDPOINT`, domainName);
4102
4049
  } else {
4103
- ctx.bind(
4104
- `PUBSUB_${constantCase5(id)}_ENDPOINT`,
4105
- api.dns.pipe((dns) => dns.HTTP)
4106
- );
4107
- ctx.bind(
4108
- `PUBSUB_${constantCase5(id)}_REALTIME_ENDPOINT`,
4109
- api.dns.pipe((dns) => dns.REALTIME)
4110
- );
4050
+ ctx.bind(`PUBSUB_${constantCase5(id)}_ENDPOINT`, endpoint.endpointAddress);
4111
4051
  }
4112
4052
  }
4053
+ },
4054
+ onStack(ctx) {
4055
+ for (const [id, props] of Object.entries(ctx.stackConfig.pubsub ?? {})) {
4056
+ const group = new Group9(ctx.stack, "pubsub", id);
4057
+ const { lambda } = createAsyncLambdaFunction(group, ctx, `pubsub`, id, props.consumer);
4058
+ const name = formatLocalResourceName({
4059
+ appName: ctx.app.name,
4060
+ stackName: ctx.stack.name,
4061
+ resourceType: "pubsub",
4062
+ resourceName: id
4063
+ });
4064
+ const topic = new $9.aws.iot.TopicRule(group, "rule", {
4065
+ name: name.replaceAll("-", "_"),
4066
+ enabled: true,
4067
+ sql: props.sql,
4068
+ sqlVersion: props.sqlVersion,
4069
+ lambda: [{ functionArn: lambda.arn }]
4070
+ });
4071
+ new $9.aws.lambda.Permission(group, "permission", {
4072
+ action: "lambda:InvokeFunction",
4073
+ principal: "iot.amazonaws.com",
4074
+ functionName: lambda.functionName,
4075
+ sourceArn: topic.arn
4076
+ });
4077
+ }
4113
4078
  }
4114
- // Note: The onStack method would handle channel namespaces and subscriptions
4115
- // but is commented out for now as it needs to be refactored for AppSync Event API
4116
- // onStack(ctx) {
4117
- // // Channel namespaces and event handlers would be configured here
4118
- // // This would include:
4119
- // // 1. Creating channel namespaces with their own auth modes (overriding defaults)
4120
- // // 2. Setting up event handlers (Lambda functions) for specific channels
4121
- // // 3. Configuring event filtering and routing rules
4122
- // },
4123
4079
  });
4124
4080
 
4125
4081
  // src/feature/queue/index.ts
@@ -5143,7 +5099,7 @@ var execCommand = async ({ cwd, env, command }) => {
5143
5099
  };
5144
5100
 
5145
5101
  // src/feature/site/index.ts
5146
- import { createHash as createHash3 } from "crypto";
5102
+ import { createHash as createHash4 } from "crypto";
5147
5103
  import { Future as Future3 } from "@awsless/formation";
5148
5104
  var siteFeature = defineFeature({
5149
5105
  name: "site",
@@ -5448,7 +5404,7 @@ var siteFeature = defineFeature({
5448
5404
  version: new Future3((resolve) => {
5449
5405
  $combine(...versions).then((versions2) => {
5450
5406
  const combined = versions2.filter((v) => !!v).sort().join(",");
5451
- const version = createHash3("sha1").update(combined).digest("hex");
5407
+ const version = createHash4("sha1").update(combined).digest("hex");
5452
5408
  resolve(version);
5453
5409
  });
5454
5410
  })
@@ -6947,7 +6903,7 @@ import deepmerge4 from "deepmerge";
6947
6903
  import { join as join16 } from "path";
6948
6904
 
6949
6905
  // src/feature/instance/build/executable.ts
6950
- import { createHash as createHash4 } from "crypto";
6906
+ import { createHash as createHash5 } from "crypto";
6951
6907
  import { readFile as readFile4 } from "fs/promises";
6952
6908
  import { join as join15 } from "path";
6953
6909
  import { exec as exec2 } from "promisify-child-process";
@@ -6962,7 +6918,7 @@ var buildExecutable = async (input, outputPath, architecture) => {
6962
6918
  }
6963
6919
  const file = await readFile4(filePath);
6964
6920
  return {
6965
- hash: createHash4("sha1").update(file).update("x86_64").digest("hex"),
6921
+ hash: createHash5("sha1").update(file).update("x86_64").digest("hex"),
6966
6922
  file
6967
6923
  };
6968
6924
  };
@@ -7166,9 +7122,10 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
7166
7122
  // 'awslogs-group': `/aws/ecs/${name}`,
7167
7123
  "awslogs-group": `/aws/lambda/${name}`,
7168
7124
  "awslogs-region": ctx.appConfig.region,
7169
- "awslogs-stream-prefix": "ecs"
7170
- // mode: 'non-blocking',
7171
- // 'max-buffer-size': '1m',
7125
+ "awslogs-stream-prefix": "ecs",
7126
+ mode: "non-blocking"
7127
+ // 'awslogs-multiline-pattern': '',
7128
+ // 'max-buffer-size': '100m',
7172
7129
  }
7173
7130
  }
7174
7131
  },
@@ -8073,6 +8030,7 @@ var createApp = (props) => {
8073
8030
  };
8074
8031
  return {
8075
8032
  app,
8033
+ appId,
8076
8034
  base,
8077
8035
  zones,
8078
8036
  ready,
@@ -8361,7 +8319,7 @@ import { join as join19 } from "path";
8361
8319
  import wildstring3 from "wildstring";
8362
8320
 
8363
8321
  // src/build/__fingerprint.ts
8364
- import { createHash as createHash5 } from "crypto";
8322
+ import { createHash as createHash6 } from "crypto";
8365
8323
  import { readdir as readdir4, readFile as readFile5, stat as stat4 } from "fs/promises";
8366
8324
  import { basename as basename4, dirname as dirname10, extname as extname4, join as join17 } from "path";
8367
8325
  import parseStaticImports from "parse-static-imports";
@@ -8372,7 +8330,7 @@ var generateFileHashes = async (file, hashes) => {
8372
8330
  }
8373
8331
  const code = await readModuleFile(file);
8374
8332
  const deps = await findDependencies(file, code);
8375
- const hash = createHash5("sha1").update(code).digest();
8333
+ const hash = createHash6("sha1").update(code).digest();
8376
8334
  hashes.set(file, hash);
8377
8335
  for (const dep of deps) {
8378
8336
  if (dep.startsWith("/")) {
@@ -8389,7 +8347,7 @@ var fingerprintFromDirectory = async (dir) => {
8389
8347
  }
8390
8348
  }
8391
8349
  const merge2 = Buffer.concat(Array.from(hashes.values()).sort());
8392
- return createHash5("sha1").update(merge2).digest("hex");
8350
+ return createHash6("sha1").update(merge2).digest("hex");
8393
8351
  };
8394
8352
  var readModuleFile = (file) => {
8395
8353
  if (file.endsWith(".js")) {
@@ -9098,7 +9056,7 @@ var run = (program2) => {
9098
9056
  const region = appConfig.region;
9099
9057
  const credentials = getCredentials(appConfig.profile);
9100
9058
  const accountId = await getAccountId(credentials, region);
9101
- const { commands: commands9 } = createApp({ appConfig, stackConfigs, accountId });
9059
+ const { commands: commands9, appId } = createApp({ appConfig, stackConfigs, accountId });
9102
9060
  let command;
9103
9061
  if (selected) {
9104
9062
  command = commands9.find((cmd) => {
@@ -9119,6 +9077,7 @@ var run = (program2) => {
9119
9077
  throw new ExpectedError(`The provided command doesn't exist.`);
9120
9078
  }
9121
9079
  process.env.APP = appConfig.name;
9080
+ process.env.APP_ID = appId;
9122
9081
  process.env.AWS_REGION = region;
9123
9082
  process.env.AWS_ACCOUNT_ID = accountId;
9124
9083
  const module = await tsImport(command.file, {
@@ -266,6 +266,10 @@ var FileCodeSchema = z11.object({
266
266
  });
267
267
  var BundleCodeSchema = z11.object({
268
268
  bundle: LocalDirectorySchema.describe("The directory that needs to be bundled.")
269
+ // dir: z.string(),
270
+ // build: z.string(),
271
+ // run: z.string(),
272
+ // cacheKey:
269
273
  });
270
274
  var CodeSchema = z11.union([
271
275
  LocalFileSchema.transform((file) => ({
Binary file
Binary file
@@ -1 +1 @@
1
- 67cc66902e9b4f4a3b10b94784c0f0f88f247ce1
1
+ 809ac79b62f213f5ced66b7a051b247cda10444b
Binary file
package/dist/server.d.ts CHANGED
@@ -87,10 +87,6 @@ interface FunctionResources {
87
87
  declare const Function: FunctionResources;
88
88
  declare const Fn: FunctionResources;
89
89
 
90
- interface InstanceResources {
91
- }
92
- declare const Instance: InstanceResources;
93
-
94
90
  declare const getMetricName: (name: string) => string;
95
91
  declare const getMetricNamespace: (stack?: string, app?: string) => string;
96
92
  interface MetricResources {
@@ -171,4 +167,4 @@ declare const Topic: TopicResources;
171
167
  declare const APP: "app";
172
168
  declare const STACK: "stack";
173
169
 
174
- export { APP, Alert, type AlertMock, type AlertMockResponse, type AlertResources, Auth, type AuthResources, Cache, type CacheResources, type CommandContext, type CommandHandler, Config, type ConfigResources, Fn, Function, type FunctionMock, type FunctionMockResponse, type FunctionResources, Instance, type InstanceResources, Metric, type MetricResources, PubSub, type PublishOptions, Queue, type QueueMock, type QueueMockResponse, type QueueResources, type RpcAuthorizerResponse, STACK, Search, type SearchResources, Store, type StoreResources, Table, type TableResources, Task, type TaskMock, type TaskMockResponse, type TaskResources, Topic, type TopicMock, type TopicMockResponse, type TopicResources, getAlertName, getAuthProps, getCacheProps, getConfigName, getConfigValue, getFunctionName, getMetricName, getMetricNamespace, getPubSubTopic, getQueueName, getQueueUrl, getSearchName, getSearchProps, getSiteBucketName, getStoreName, getTableName, getTaskName, getTopicName, mockAlert, mockCache, mockFunction, mockMetric, mockPubSub, mockQueue, mockTask, mockTopic, pubsubAuthorizerHandle, pubsubAuthorizerResponse, setConfigValue };
170
+ export { APP, Alert, type AlertMock, type AlertMockResponse, type AlertResources, Auth, type AuthResources, Cache, type CacheResources, type CommandContext, type CommandHandler, Config, type ConfigResources, Fn, Function, type FunctionMock, type FunctionMockResponse, type FunctionResources, Metric, type MetricResources, PubSub, type PublishOptions, Queue, type QueueMock, type QueueMockResponse, type QueueResources, type RpcAuthorizerResponse, STACK, Search, type SearchResources, Store, type StoreResources, Table, type TableResources, Task, type TaskMock, type TaskMockResponse, type TaskResources, Topic, type TopicMock, type TopicMockResponse, type TopicResources, getAlertName, getAuthProps, getCacheProps, getConfigName, getConfigValue, getFunctionName, getMetricName, getMetricNamespace, getPubSubTopic, getQueueName, getQueueUrl, getSearchName, getSearchProps, getSiteBucketName, getStoreName, getTableName, getTaskName, getTopicName, mockAlert, mockCache, mockFunction, mockMetric, mockPubSub, mockQueue, mockTask, mockTopic, pubsubAuthorizerHandle, pubsubAuthorizerResponse, setConfigValue };
package/dist/server.js CHANGED
@@ -1,6 +1,3 @@
1
- import {
2
- shortId
3
- } from "./chunk-W4ED7XCC.js";
4
1
  import {
5
2
  createProxy
6
3
  } from "./chunk-2LRBH7VV.js";
@@ -456,13 +453,6 @@ var Config = /* @__PURE__ */ new Proxy(
456
453
  }
457
454
  );
458
455
 
459
- // src/lib/server/instance.ts
460
- var Instance = /* @__PURE__ */ createProxy((stack) => {
461
- return createProxy((name) => {
462
- return `http://${shortId(`${stack}:${name}`)}.${APP}`;
463
- });
464
- });
465
-
466
456
  // src/lib/server/metric.ts
467
457
  import {
468
458
  batchPutData,
@@ -678,7 +668,6 @@ export {
678
668
  Config,
679
669
  Fn,
680
670
  Function,
681
- Instance,
682
671
  Metric,
683
672
  PubSub,
684
673
  QoS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awsless/awsless",
3
- "version": "0.0.579",
3
+ "version": "0.0.581",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -33,23 +33,23 @@
33
33
  ]
34
34
  },
35
35
  "peerDependencies": {
36
- "@awsless/big-float": "^0.1.4",
36
+ "@awsless/big-float": "^0.1.5",
37
37
  "@awsless/cloudwatch": "^0.0.1",
38
38
  "@awsless/duration": "^0.0.3",
39
- "@awsless/clui": "^0.0.7",
39
+ "@awsless/dynamodb": "^0.2.12",
40
40
  "@awsless/iot": "^0.0.3",
41
- "@awsless/json": "^0.0.10",
42
- "@awsless/dynamodb": "^0.2.10",
43
41
  "@awsless/lambda": "^0.0.33",
44
- "@awsless/mqtt": "^0.0.2",
42
+ "@awsless/json": "^0.0.10",
43
+ "@awsless/clui": "^0.0.7",
45
44
  "@awsless/open-search": "^0.0.21",
46
45
  "@awsless/redis": "^0.0.14",
47
- "@awsless/s3": "^0.0.21",
48
46
  "@awsless/sns": "^0.0.10",
49
- "@awsless/sqs": "^0.0.15",
47
+ "@awsless/sqs": "^0.0.16",
50
48
  "@awsless/ssm": "^0.0.7",
51
49
  "@awsless/validate": "^0.0.19",
52
- "@awsless/weak-cache": "^0.0.1"
50
+ "@awsless/weak-cache": "^0.0.1",
51
+ "@awsless/mqtt": "^0.0.2",
52
+ "@awsless/s3": "^0.0.21"
53
53
  },
54
54
  "dependencies": {
55
55
  "@arcanyx/cidr-slicer": "^0.3.0",
@@ -134,17 +134,17 @@
134
134
  "zip-a-folder": "^3.1.6",
135
135
  "zod": "^3.24.2",
136
136
  "zod-to-json-schema": "^3.24.3",
137
- "@awsless/big-float": "^0.1.4",
137
+ "@awsless/big-float": "^0.1.5",
138
138
  "@awsless/cloudwatch": "^0.0.1",
139
- "@awsless/clui": "^0.0.7",
140
- "@awsless/formation": "^0.0.80",
141
139
  "@awsless/graphql": "^0.0.9",
142
140
  "@awsless/duration": "^0.0.3",
141
+ "@awsless/formation": "^0.0.80",
143
142
  "@awsless/json": "^0.0.10",
144
143
  "@awsless/scheduler": "^0.0.4",
145
- "@awsless/size": "^0.0.2",
146
144
  "@awsless/validate": "^0.0.19",
147
- "@awsless/ts-file-cache": "^0.0.12"
145
+ "@awsless/clui": "^0.0.7",
146
+ "@awsless/ts-file-cache": "^0.0.12",
147
+ "@awsless/size": "^0.0.2"
148
148
  },
149
149
  "devDependencies": {
150
150
  "@node-rs/bcrypt": "^1.10.5",
@@ -1,9 +0,0 @@
1
- // src/util/id.ts
2
- import { createHash } from "crypto";
3
- var shortId = (ns) => {
4
- return createHash("md5").update(ns).digest("hex").substring(0, 10);
5
- };
6
-
7
- export {
8
- shortId
9
- };