Git Product home page Git Product logo

ion's Introduction

SST

Discord npm Build status


SST makes it easy to build modern full-stack applications on AWS. Watch the SST in 100 seconds video to learn more.

$ npx create-sst@latest

Pick your frontend

Deploy Next.js, Svelte, Remix, Astro, Solid, or any static site to AWS.

Add any feature

SST gives you the full power of AWS. Making it easy to add any feature to your product.

  • File uploads — Allow your users to upload files to S3.
  • Auth — Authenticate your users through any auth provider.
  • Events — Run tasks after your app has returned to your user.
  • Databases — Use a serverless SQL or NoSQL database to power your app.
  • Jobs — Run cron jobs or long running jobs powered by serverless functions.
  • APIs — Add a dedicated serverless REST, GraphQL, or WebSocket API to your app.

Collaborate with your team

Finally, you can git push to deploy using SEED, a service built by the team behind SST. And you can work on your apps together with your team with automatic preview environments.


Join our community Discord | YouTube | Twitter | Contribute

ion's People

Contributors

0xcadams avatar antonmoller avatar arjunyel avatar atticoos avatar cmanou avatar conico974 avatar danieladarve avatar ernxst avatar fwang avatar garretcharp avatar janstevens avatar jayair avatar jonlambert avatar juniyadi avatar khalil-omer avatar kldeb avatar kwigley avatar lukasmurdock avatar lukeshay avatar miguelvictor avatar namesmt avatar notorioussledge avatar roguesherlock avatar san4d avatar shreyassanthu77 avatar thdxr avatar theknightcoder avatar thomkrupa avatar zohaibakber avatar zxt-tzx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ion's Issues

Postgres - Add option for high availability

Currently when you use the postgres component it will only have 1 instance in 1 AZ. Would be nice to have options for high availability running in multi-az so it can failover if needed


If you've already posted your issue on Discord, make sure to leave a link to it here.

ION-245

Error providing `aws.allowedAccountIds` in `sst.config.ts`

In particular setting providers.aws.allowedAccountIds in Config.app of sst.config.ts which has typescript type $util.Input<$util.Input<string>[]> which is basically string[] gives

panic: json: cannot unmarshal array into Go struct field App.providers of type string

goroutine 1 [running]:
main.main()
    /home/runner/work/ion/ion/cmd/sst/main.go:659 +0xa88

Looks like it's to do with the struct for app providers only allowing string values in the following file.

Providers map[string]map[string]string `json:"providers"`

Error using hono's streamHandle with sst dev: awslambda is not defined

When using hono's streamHandle (which wraps the handle with awslambda.streamifyResponse()) with sst dev, we get the following error:

|  Error       awslambda is not defined
|              ↳ at streamHandle (/Users/<user>/<repo>/node_modules/hono/dist/adapter/aws-lambda/handler.js:17:3)
|              ↳ at <anonymous> (/Users/<user>/<repo>/packages/server/src/main.ts:120:24)
|              ↳ at ModuleJob.run (node:internal/modules/esm/module_job:194:25)

In sst config:

    const api = new sst.aws.Function("Api", {
      handler: "packages/server/src/main.handler",
      url: true,
      link: [
        secrets.anthropicApiKey,
        secrets.openaiApiKey,
      ],
      streaming: true,
    });

Discord Link

Support `basePath` in Nextjs

As described in this issue in sst/sst and as addressed in this sst/sst PR, if basePath is set in next.config.js, sst/ion ignores that path when defining Cloudfront routes, so Next expects assets at /basepath/_next/foo but Cloudfront is serving them at _next/foo.

NextJS Warmer Fails to Deploy

When I set warm: 5 on my nextjs component I get the following error on deploy:

VisibleError: Could not find handler file "index.handler" for function "WebWarmer"

If you've already posted your issue on Discord, make sure to leave a link to it here.

sst dev/deploy output not logging error correctly

v0.0.200
I found an error message that is getting chopped up unhelpfully in the output. The sst run dev failure looks like:

|  900 seconds
|  {
|  {
|  400,
|  "4b3c8415-400f-437c-b1ea-af1a5c771c41"
|  },
|  900 seconds",
|  "User"
|  }

×  Failed
   BookEmbeddingQueue sst:aws:Queue → BookEmbeddingQueueEventSourceMapping aws:lambda:EventSourceMapping
   900 seconds
   {
   {
   400,
   "4b3c8415-400f-437c-b1ea-af1a5c771c41"
   },
   900 seconds",
   "User"
   }

Wheras the output in event.log is:

{"sequence":694,"timestamp":1711461814,"diagnosticEvent":{"urn":"urn:pulumi:aboza::stacks-ils-ion::sst:aws:Queue$aws:lambda/eventSourceMapping:EventSourceMapping::BookEmbeddingQueueEventSourceMapping","prefix":"error: ","message":"1 error occurred:\n\t* creating Lambda Event Source Mapping (arn:aws:sqs:us-east-1:058264306954:stacks-ils-ion-aboza-BookEmbeddingQueueQueue): InvalidParameterValueException: Queue visibility timeout: 30 seconds is less than Function timeout: 900 seconds\n{\n  RespMetadata: {\n    StatusCode: 400,\n    RequestID: \"4b3c8415-400f-437c-b1ea-af1a5c771c41\"\n  },\n  Message_: \"Queue visibility timeout: 30 seconds is less than Function timeout: 900 seconds\",\n  Type: \"User\"\n}\n\n\n","color":"never","severity":"error"},"Error":null}

If you've already posted your issue on Discord, make sure to leave a link to it here.
https://discord.com/channels/983865673656705025/1177071497974648952/1222185055720571033

Unable to deploy NextJS Site

When following the docs directions for getting started with NextJS, I receive the following error below. This has been happening starting with version 0.0.119 all the way to the current version 0.0.128

Running "npx --yes [email protected] build" script
Next.js v14.1.3
OpenNext v3.0.0-rc.5
┌─────────────────────────────────┐
│ OpenNext — Building Next.js app │
└─────────────────────────────────┘
> [email protected] build
> next build
   ▲ Next.js 14.1.3
   Creating an optimized production build ...
(node:24321) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
(node:24337) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
 ✓ Compiled successfully
   Linting and checking validity of types ...
Failed to compile.
.sst/platform/src/components/aws/ssr-site.ts:1198:39
Type error: Type 'string | UnwrappedArray<string>' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
  1196 |             });
  1197 |           } else {
> 1198 |             invalidationPaths.push(...(invalidation?.paths || []));
       |                                       ^
  1199 |           }
  1200 |           if (invalidationPaths.length === 0) return;
  1201 |
node:internal/errors:956
  const err = new Error(message);
              ^
Error: Command failed: npm run build
    at genericNodeError (node:internal/errors:956:15)
    at wrappedFn (node:internal/errors:510:14)
    at checkExecSyncError (node:child_process:890:11)
    at Object.execSync (node:child_process:962:15)
    at buildNextjsApp (file:///Users/sunitkulkarni/.npm/_npx/243dd04f789c84f7/node_modules/open-next/dist/build.js:133:8)
    at build (file:///Users/sunitkulkarni/.npm/_npx/243dd04f789c84f7/node_modules/open-next/dist/build.js:36:11) {
  status: 1,
  signal: null,
  output: [ null, null, null ],
  pid: 24289,
  stdout: null,
  stderr: null
}
Node.js v21.5.0
(node:24256) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
|  Creating    sst:aws:Nextjs → QleoIon
(node:24256) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 22)
(node:24256) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 23)
|  Creating    sst:aws:Nextjs → sst:aws:Bucket → QleoIonAssets
|  Created     sst:aws:Nextjs → sst:aws:Bucket → QleoIonAssets (8ms)
|  Error
|  VisibleError: There was a problem building the "QleoIon" site.
|      at file:///Users/sunitkulkarni/QleoCode/next-ion/.sst/platform/src/components/aws/ssr-site.ts:469:17
|      at /Users/sunitkulkarni/QleoCode/next-ion/.sst/platform/node_modules/@pulumi/output.ts:398:31
|      at Generator.next (<anonymous>)
|      at /Users/sunitkulkarni/QleoCode/next-ion/.sst/platform/node_modules/@pulumi/pulumi/output.js:21:71
|      at new Promise (<anonymous>)
|      at __awaiter (/Users/sunitkulkarni/QleoCode/next-ion/.sst/platform/node_modules/@pulumi/pulumi/output.js:17:12)
|      at applyHelperAsync (/Users/sunitkulkarni/QleoCode/next-ion/.sst/platform/node_modules/@pulumi/pulumi/output.js:239:12)
|      at /Users/sunitkulkarni/QleoCode/next-ion/.sst/platform/node_modules/@pulumi/output.ts:310:13 {
|    promise: Promise { <rejected> [Circular *1] }
|  }
|  Creating    sst:aws:Nextjs → sst:aws:Bucket → random:index:RandomId → QleoIonAssetsId
|  Created     sst:aws:Nextjs → sst:aws:Bucket → random:index:RandomId → QleoIonAssetsId (4ms)
|  Creating    sst:aws:Nextjs → aws:cloudfront:OriginAccessIdentity → QleoIonOriginAccessIdentity
|  Creating    sst:aws:Nextjs → sst:aws:Bucket → aws:s3:BucketV2 → QleoIonAssetsBucket
|  Created     sst:aws:Nextjs → aws:cloudfront:OriginAccessIdentity → QleoIonOriginAccessIdentity (518ms)
|  Created     sst:aws:Nextjs → sst:aws:Bucket → aws:s3:BucketV2 → QleoIonAssetsBucket (737ms)
|  Creating    sst:aws:Nextjs → sst:aws:Bucket → aws:s3:BucketPublicAccessBlock → QleoIonAssetsPublicAccessBlock
|  Creating    sst:aws:Nextjs → sst:aws:Bucket → aws:s3:BucketCorsConfigurationV2 → QleoIonAssetsCors
|  Created     sst:aws:Nextjs → sst:aws:Bucket → aws:s3:BucketPublicAccessBlock → QleoIonAssetsPublicAccessBlock (121ms)
|  Creating    sst:aws:Nextjs → sst:aws:Bucket → aws:s3:BucketPolicy → QleoIonAssetsPolicy
|  Created     sst:aws:Nextjs → sst:aws:Bucket → aws:s3:BucketPolicy → QleoIonAssetsPolicy (8.562s)
|  Created     sst:aws:Nextjs → sst:aws:Bucket → aws:s3:BucketCorsConfigurationV2 → QleoIonAssetsCors (15.81s)


❌ Failed
   VisibleError: There was a problem building the "QleoIon" site.
       at file:///Users/sunitkulkarni/QleoCode/next-ion/.sst/platform/src/components/aws/ssr-site.ts:469:17
       at /Users/sunitkulkarni/QleoCode/next-ion/.sst/platform/node_modules/@pulumi/output.ts:398:31
       at Generator.next (<anonymous>)
       at /Users/sunitkulkarni/QleoCode/next-ion/.sst/platform/node_modules/@pulumi/pulumi/output.js:21:71
       at new Promise (<anonymous>)
       at __awaiter (/Users/sunitkulkarni/QleoCode/next-ion/.sst/platform/node_modules/@pulumi/pulumi/output.js:17:12)
       at applyHelperAsync (/Users/sunitkulkarni/QleoCode/next-ion/.sst/platform/node_modules/@pulumi/pulumi/output.js:239:12)
       at /Users/sunitkulkarni/QleoCode/next-ion/.sst/platform/node_modules/@pulumi/output.ts:310:13 {
     promise: Promise { <rejected> [Circular *1] }
   }

If you've already posted your issue on Discord, make sure to leave a link to it here.
https://discord.com/channels/983865673656705025/1177071497974648952/1214751817590640732

CloudFront returns "null" for dynamic routes in Node 20 and NextJs

When upgrading from ion version 0.0.169 to 0.0.170 (and confirmed the issue still exists in 0.0.188), certain dynamic routes are simply returning "null" - no logs have shown up SST Console and I haven't found anything pertinent to the cause yet

image

Downgrading to version 0.0.169 resolves the issue. From there, manually upgrading the Default Site function to Node 20 (x86) causes it again. I'm running [email protected]


Initial discord link: https://discord.com/channels/983865673656705025/1177071497974648952/1219813905036214413

From SyncLinear.com | ION-213

Uploaded file must be a non-empty zip

After initializing a fresh NextJS repo with npx create-next-app@latest and then initializing sst inside that repo with sst init, I then attempt to run sst deploy. However, I get the following error:

 ~/QleoCode/next-ion   main ±  sst deploy
SST ❍ ion 0.0.199  ready!

➜  App:        next-ion
   Stage:      sunitkulkarni

~  Deploying

Running "npx --yes [email protected] build" script
Next.js v14.1.4
OpenNext v3.0.0-rc.8
┌─────────────────────────────────┐
│ OpenNext — Building Next.js app │
└─────────────────────────────────┘
> [email protected] build
> next build
   ▲ Next.js 14.1.4
   Creating an optimized production build ...
(node:85404) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
(node:85485) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
 ✓ Compiled successfully
   Linting and checking validity of types ...
   Collecting page data ...
   Generating static pages (0/5) ...
   Generating static pages (1/5)
   Generating static pages (2/5)
   Generating static pages (3/5)
 ✓ Generating static pages (5/5)
   Finalizing page optimization ...
   Collecting build traces ...
Route (app)                              Size     First Load JS
┌ ○ /                                    5.39 kB        89.7 kB
└ ○ /_not-found                          882 B          85.2 kB
+ First Load JS shared by all            84.3 kB
  ├ chunks/69-1656e2cc92fa6e80.js        29 kB
  ├ chunks/fd9d1056-d03af0e963d7a2f3.js  53.4 kB
  └ other shared chunks (total)          1.9 kB
○  (Static)  prerendered as static content
┌──────────────────────────────┐
│ OpenNext — Generating bundle │
└──────────────────────────────┘
Bundling middleware function...
Bundling static assets...
Bundling cache assets...
Bundling revalidation function...
Bundling image optimization function...
Bundling warmer function...
OpenNext build complete.
(node:85266) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
|  Creating    Ion sst:aws:Nextjs
|  Creating    Ion sst:aws:Nextjs → IonAssets sst:aws:Bucket
|  Created     Ion sst:aws:Nextjs → IonAssets sst:aws:Bucket
|  Creating    Ion sst:aws:Nextjs → IonOriginAccessIdentity sst:aws:OriginAccessIdentity
|  Creating    Ion sst:aws:Nextjs → IonOpenNextOutput sst:aws:Cache
|  Creating    Ion sst:aws:Nextjs → IonAssetsId random:index:RandomId
|  Created     Ion sst:aws:Nextjs → IonOpenNextOutput sst:aws:Cache
|  Created     Ion sst:aws:Nextjs → IonAssetsId random:index:RandomId
|  Creating    Ion sst:aws:Nextjs → IonRevalidationSeeder sst:aws:Function
|  Creating    Ion sst:aws:Nextjs → IonRevalidationQueue sst:aws:Queue
|  Creating    Ion sst:aws:Nextjs → IonRevalidationTable aws:dynamodb:Table
|  Creating    Ion sst:aws:Nextjs → IonAssetsBucket aws:s3:BucketV2
|  Created     Ion sst:aws:Nextjs → IonRevalidationSeeder sst:aws:Function
|  Created     Ion sst:aws:Nextjs → IonRevalidationQueue sst:aws:Queue
|  Creating    Ion sst:aws:Nextjs → IonRevalidationQueueQueue aws:sqs:Queue
|  Creating    Ion sst:aws:Nextjs → IonRevalidationSeederLogGroup aws:cloudwatch:LogGroup
|  Creating    Ion sst:aws:Nextjs → IonRevalidationSeederCode aws:s3:BucketObjectv2
|  Created     Ion sst:aws:Nextjs → IonRevalidationSeederLogGroup aws:cloudwatch:LogGroup
|  Created     Ion sst:aws:Nextjs → IonRevalidationSeederCode aws:s3:BucketObjectv2
|  Created     Ion sst:aws:Nextjs → IonAssetsBucket aws:s3:BucketV2
|  Creating    Ion sst:aws:Nextjs → IonAssetsPublicAccessBlock aws:s3:BucketPublicAccessBlock
|  Creating    Ion sst:aws:Nextjs → IonAssetsCors aws:s3:BucketCorsConfigurationV2
|  Created     Ion sst:aws:Nextjs → IonAssetsPublicAccessBlock aws:s3:BucketPublicAccessBlock
|  Created     Ion sst:aws:Nextjs → IonOriginAccessIdentity sst:aws:OriginAccessIdentity (2.0s)
|  Creating    Ion sst:aws:Nextjs → IonAssetsPolicy aws:s3:BucketPolicy
|  Created     Ion sst:aws:Nextjs → IonAssetsPolicy aws:s3:BucketPolicy (8.0s)
|  Created     Ion sst:aws:Nextjs → IonAssetsCors aws:s3:BucketCorsConfigurationV2 (15.8s)
|  Created     Ion sst:aws:Nextjs → IonRevalidationTable aws:dynamodb:Table (23.0s)
|  Creating    Ion sst:aws:Nextjs → IonRevalidationSeederRole aws:iam:Role
|  Created     Ion sst:aws:Nextjs → IonRevalidationSeederRole aws:iam:Role
|  Creating    Ion sst:aws:Nextjs → IonRevalidationSeederFunction aws:lambda:Function
|  Error       Ion sst:aws:Nextjs → IonRevalidationSeederFunction aws:lambda:Function Uploaded file must be a non-empty zip
|  Created     Ion sst:aws:Nextjs → IonRevalidationQueueQueue aws:sqs:Queue (25.3s)

×  Failed
   Ion sst:aws:Nextjs → IonRevalidationSeederFunction aws:lambda:Function
   Uploaded file must be a non-empty zip

×  Unexpected error occurred. Please check the logs or run with --verbose for more details.

As for my sst.config.ts file, here are the contents:

/// <reference path="./.sst/platform/config.d.ts" />

export default $config({
  app(input) {
    return {
      name: "next-ion",
      removal: input?.stage === "production" ? "retain" : "remove",
      home: "aws",
    };
  },
  async run() {
    const site = new sst.aws.Nextjs("Ion", {
      domain: {
        hostedZone: "dev.qleo.ai",
        domainName: "ion.dev.qleo.ai",
      }
    });

    return {
      url: site.url,
    }
  },
});


If you've already posted your issue on Discord, make sure to leave a link to it here.

ION-218

PostHog max message size exceeded

When calling posthog-go to log errors from the CLI, a very big body is being passed leading to PostHog failing to send the message.

posthog 2024/03/19 05:55:10 ERROR: the message exceeds the maximum allowed size - 
{capture posthog-go 2.0.0 2024-03-19 05:55:10.264735821 +0000 UTC m=+227.122804259 
knzmukmbuxfvbnrwdsmzxrhawoxekado 
cli.error map[$lib:posthog-go $lib_version:2.0.0 ci_name:GitHub Actions
cpu_count:4 error:failed to run update: exit status 255

Consider truncating the stdout dump you are passing to PostHog if size exceeds x.

README Typo

Neat work! minor typo here:
CleanShot 2023-12-22 at 19 47 40@2x

Not sure what it was supposed to say otherwise would submit a PR.

`remove` command nil pointer dereference

This seems to have been introduced in the 5xx versions, but I am experiencing it in 161

sst remove --stage=testing123 --verbose
time=2024-03-17T10:58:16.731-07:00 level=INFO msg="initializing project" version=0.0.161
time=2024-03-17T10:58:16.733-07:00 level=INFO msg="esbuild building"
time=2024-03-17T10:58:16.741-07:00 level=INFO msg="esbuild built"
time=2024-03-17T10:58:16.741-07:00 level=INFO msg="sending eval message" module=/Users/khalil_work/GitHub/pivot/.sst/eval/eval-1710698296732.mjs
time=2024-03-17T10:58:16.762-07:00 level=INFO msg="checking platform"
time=2024-03-17T10:58:16.764-07:00 level=INFO msg="credentials found"
time=2024-03-17T10:58:16.764-07:00 level=INFO msg="fetching bootstrap"
time=2024-03-17T10:58:17.524-07:00 level=INFO msg="found existing bootstrap" data="{\"version\":1,\"asset\":\"sst-asset-tchzobzfnhbe\",\"state\":\"sst-state-tchzobzfnhbe\"}"
time=2024-03-17T10:58:17.524-07:00 level=INFO msg="loaded config" app=next stage=testing123
SST ❍ ion 0.0.161  ready!

➜  App:        next
   Stage:      testing123

time=2024-03-17T10:58:17.524-07:00 level=INFO msg="running stack command" cmd=destroy
~  Removing

time=2024-03-17T10:58:17.524-07:00 level=INFO msg="INFO locking app=next stage=testing123"
time=2024-03-17T10:58:17.524-07:00 level=INFO msg="INFO getting data key=lock app=next stage=testing123"
time=2024-03-17T10:58:17.816-07:00 level=ERROR msg="exited with error" err=""

Discord message: https://discord.com/channels/983865673656705025/1177071497974648952/1218995682938191872

Error creating NextJsSite - Conflicting Names due to AssetPolicy

In

function createS3Bucket() {
const bucket = new Bucket(
`${name}Assets`,

it creates the bucket ${name}Assets which then creates a policy internally
new aws.s3.BucketPolicy(
`${name}Policy`,

which appends Policy, but then in SsrSite we also create a bucket policy with the the same suffix AssetsPolicy
new aws.s3.BucketPolicy(
`${name}AssetsPolicy`,
which ends up conflicting.

VisibleError: Invalid component name "WebAssetsPolicy". Component names must be unique.
    at file:///.../.sst/platform/src/auto/run.ts:39:13
    at new Resource (/.../.sst/platform/node_modules/@pulumi/resource.ts:399:26)
    at new CustomResource (/.../.sst/platform/node_modules/@pulumi/resource.ts:897:9)
    at new BucketPolicy (/.../.sst/platform/node_modules/@pulumi/s3/bucketPolicy.ts:116:9)
    at file:///.../.sst/platform/src/components/aws/bucket.ts:237:11
    at /.../.sst/platform/node_modules/@pulumi/output.ts:398:31
    at Generator.next (<anonymous>)
    at /.../.sst/platform/node_modules/@pulumi/pulumi/output.js:21:71
    at new Promise (<anonymous>)
    at __awaiter (/.../.sst/platform/node_modules/@pulumi/pulumi/output.js:17:12)

Additionally you are only allowed one bucket policy and last write wins, so even if the names don't conflict there is an issue.

sst.aws.Router - Support for Cloudfront functions for viewer requests

It would be nice to either directly or via transforms allow people to add viewer request functions and the like to routes in the router. My use case is to strip the prefix before it gets to the underlying function url , and also add additional headers to the request.

Alternative would be just exposing the Cdn resource so it can be done that way.

The current escape hatch I am doing is using pulumi directly means you also have to mess around with the dns validation etc, which is painful

ION-212

SSO support

I use AWS SSO with different profiles for each environment, I am trying to migrate over to ion but running into issues when trying to deploy.

Running into the issue: Error initializing provider aws: failed to refresh cached credentials, no EC2 IMDS role found, operation error ec2imds: GetMetadata, exceeded maximum number of attempts, 3, request send failed

My config is basic and looks like this:

export default $config({
  app(input) {
    return {
      name: "SESSION_NAME",
      removal: input?.stage === "production" ? "retain" : "remove",
      profile: input?.stage === "production" ? "production" : "default",
      home: "aws",
      providers: {
        aws: {
          region: "ap-southeast-2",
          role: {
            duration_seconds: 3600,
            session_name: "SESSION_NAME",
          },
        },
      },
    };
  },

Nextjs sst deploy fails (0.0.131) due to favicon format.

After fixing the same error as #22 by excluding sst.config.ts in tsconfig, deploy resulted in a different error. I've upgraded to 0.0.131.

  • simple static site, next@14
  • sst dev works locally
  • nextjs build/linting works
  • But sst deploy --stage=test fails.

When I directly run npx --yes [email protected] build, the output is:

Bundling middleware function...
Bundling static assets...
Bundling cache assets...
node:fs:456
    return binding.readFileUtf8(path, stringToFlags(options.flag));
                   ^

Error: ENOENT: no such file or directory, open '/Users/bebbi/code/landing/.next/standalone/.next/server/app/icon/route.js.nft.json'
    at readFileSync (node:fs:456:20)
    at computeCopyFilesForPage (file:///Users/bebbi/.npm/_npx/243dd04f789c84f7/node_modules/open-next/dist/build/copyTracedFiles.js:39:42)

Ran "sst init --verbose" on mac m1 chip.

time=2024-03-26T16:26:37.452-05:00 level=INFO msg="copying template" path=templates/nextjs/files/sst-env.d.ts
time=2024-03-26T16:26:37.453-05:00 level=INFO msg="copying template" path=templates/nextjs/files/sst.config.ts
time=2024-03-26T16:26:37.453-05:00 level=INFO msg=patching file=tsconfig.json
time=2024-03-26T16:26:37.454-05:00 level=ERROR msg="exited with error" err="invalid state detected\ngithub.com/evanphx/json-patch/v5.init\n\t<autogenerated>:1\nruntime.doInit1\n\t/opt/hostedtoolcache/go/1.22.1/x64/src/runtime/proc.go:7176\nruntime.doInit\n\t/opt/hostedtoolcache/go/1.22.1/x64/src/runtime/proc.go:7143\nruntime.main\n\t/opt/hostedtoolcache/go/1.22.1/x64/src/runtime/proc.go:253\nruntime.goexit\n\t/opt/hostedtoolcache/go/1.22.1/x64/src/runtime/asm_arm64.s:1222"
×  Unexpected error occurred. Please check the logs or run with --verbose for more details.

For context, I'm using Prisma in my project. I'm thinking Prisma has separate engine that crashes SST. I've dealt with it on the older version of SST.

Note this line:
\nruntime.goexit\n\t/opt/hostedtoolcache/go/1.22.1/x64/src/runtime/asm_arm64.s:1222

Unable to complete basic bootstrap of Nextjs (deploy). Silent error.

Silently errors with no further information. Attempting to deploy to different stages does not work. Is there a cache somewhere that I can purge? I am unfamiliar with the internals but it appears to be looking at a state called sst-state-moaobbrevrem.

time=2024-03-15T08:46:44.093Z level=INFO msg="initializing project" version=0.0.144
time=2024-03-15T08:46:44.098Z level=INFO msg="esbuild building"
time=2024-03-15T08:46:44.102Z level=INFO msg="esbuild built"
time=2024-03-15T08:46:44.102Z level=INFO msg="sending eval message" module=/Users/dominichadfield/Github/my-app/.sst/eval/eval-1710492404098.mjs
time=2024-03-15T08:46:44.129Z level=INFO msg="checking platform"
time=2024-03-15T08:46:44.130Z level=INFO msg="credentials found"
time=2024-03-15T08:46:44.130Z level=INFO msg="fetching bootstrap"
time=2024-03-15T08:46:44.299Z level=INFO msg="found existing bootstrap" data="{\"version\":1,\"asset\":\"sst-asset-moaobbrevrem\",\"state\":\"sst-state-moaobbrevrem\"}"
time=2024-03-15T08:46:44.299Z level=INFO msg="loaded config" app=my-app stage=test
time=2024-03-15T08:46:44.299Z level=INFO msg="running stack command" cmd=up
time=2024-03-15T08:46:44.299Z level=INFO msg="INFO locking app=my-app stage=test"
time=2024-03-15T08:46:44.299Z level=INFO msg="INFO getting data key=lock app=my-app stage=test"
time=2024-03-15T08:46:44.458Z level=ERROR msg="exited with error" err=""

Comments in tsconfig.json will throw an error at sst create

This happens in t3 app which after bootstrapping comes with comments in tsconfig file as a guide

Comments :
/* Base Options: */

Error:
panic: invalid character '/' looking for beginning of object key string

file: pkg/project/create.go

Solution:
Comments should be removed or ignored before Unmarshal as / is not valid json

func Create(templateName string) error {
	if _, err := os.Stat("sst.config.ts"); err == nil {
		return fmt.Errorf("sst.config.ts already exists")
	}

	currentDirectory, err := os.Getwd()
	if err != nil {
		return nil
	}
	directoryName := strings.ToLower(filepath.Base(currentDirectory))
	slog.Info("creating project", "name", directoryName)

	presetBytes, err := components.Templates.ReadFile(filepath.Join("templates", templateName, "preset.json"))
	if err != nil {
		fmt.Printf("Error before %v", presetBytes)
		return err
	}

	fmt.Printf("Before removing comments: %s\n", presetBytes)
	presetBytes = removeComments(presetBytes)
	fmt.Printf("After removing comments: %s\n", presetBytes)
	fmt.Printf("Error after %v", presetBytes)
	var preset preset
	err = json.Unmarshal(presetBytes, &preset)
	if err != nil {
		fmt.Printf("Error at bytes%v", presetBytes)
		return err
	}
	```


Error after [..... ] Error creating project: invalid character '/' looking for beginning of object key string

Intermittent "no such file or directory" failure during deploy

There seems to be some race condition in the deployment process because occasionally I get an error like so when running sst deploy:

|  Updating    MarcRecordQueue sst:aws:Queue → MarcRecordQueueSubscriberRole aws:iam:Role
|  Error       
|  Error: Failed to build function: Error: ENOENT: no such file or directory, rename '/Users/aboza/coracorp/stacks-ils-ion/.sst/artifacts/BookEmbeddingQueueSubscriber-src/packages/functions/src/consumeBookEmbeddingQueue/handler.mjs.map' -> '/Users/aboza/coracorp/stacks-ils-ion/.sst/artifacts/BookEmbeddingQueueSubscriber-map/handler.mjs.map'
|      at file:///Users/aboza/coracorp/stacks-ils-ion/.sst/platform/src/components/aws/function.ts:1103:21 {
|    promise: Promise { <rejected> [Circular *1] }
|  }

ION-217

Multi-region regional Lambda

Just brainstorming here:

For sites that need the full Node runtime or have some other reason to use regional Lambda rather than AWS or Cloudflare edge, it can still be beneficial to have a bit of multi-region for latency. For example, us-east, us-west, eu. There needs to be some glue between the single CloudFront distribution and the multiple copies of the server Lambda (to use a Nextjs example). Could this be Route53 or is Global Accelerator (expensive 👎 ) the only viable option? I'm not sure.

ION-211

Unable to link Queue handler to Queue

I have this queue, and I want the handler to be able to delete the received queue message. I have this in my run impl:

    const bookEmbeddingQueue = new sst.aws.Queue("BookEmbeddingQueue");
    bookEmbeddingQueue.subscribe({
      handler: "packages/functions/src/consumeBookEmbeddingQueue/handler.main",
      link: [OpenApiKey, NeonDatabaseUrl, bookEmbeddingQueue],
      timeout: "900 seconds",
    });

And after adding bookEmbeddingQueue into the link array, I got this error when running sst dev:

The Pulumi runtime detected that 1533 promises were still active
at the time that the process exited. There are a few ways that this can occur:
  * Not using `await` or `.then` on a Promise returned from a Pulumi API
  * Introducing a cyclic dependency between two Pulumi Resources
  * A bug in the Pulumi Runtime
Leaving promises active is probably not what you want. If you are unsure about
why you are seeing this message, re-run your program with the `PULUMI_DEBUG_PROMISE_LEAKS`
environment variable. The Pulumi runtime will then print out additional
debug information about the leaked promises.
|  Error       

×  Failed

relates to: https://discord.com/channels/983865673656705025/1221105015939272795

ION-228

`copyFiles` in Function not working for `sst dev` (`live`)

Files passed through copyFiles option are not bundled in resulting Function bundle in live environment.

Sample config:

export default $config({
  app(input) {
    return {
      name: "test-sst-ion-function",
      removal: input?.stage === "production" ? "retain" : "remove",
      home: "aws",
    };
  },
  async run() {
    new sst.aws.Function("TestIonFunctionBundling", {
      handler: "index.handler",
      copyFiles: [
        {
          from: "abc.js",
        },
      ],
      runtime: "nodejs20.x",
    });
  },
});

I created a simple Function that when called, lists contents of current directory and directory above. abc.js currently will not be listed, when running sst dev. It prints out contents of a local .sst/artifacts/<my_function> directory.

* However, the .zip of the AWS Lambda will have the abc.js file and a bootstrap executable. This made me think that abc.js is added only after the Function code is bundled.

Running sst deploy will correctly bundle abc.js and Function code which means this issue happens only in live.

I would assume that in live environment, files passed in copyFiles array would be bundled with Function code. This would allow me to test my application before doing a deploy.

Note: Let me know if you need a repro, logs or any other details

Handle non-standard package names for Pulumi providers

https://github.com/sst/ion/blob/4fdc960ccf1cc35ab76d4050eeb012c6a336c2d5/pkg/project/install.go#L12C1-L14C2

Currently, ion assumes that all Pulumi provider packages follow the naming convention "@pulumi/provider". However, some providers, such as the Upstash provider, use a different package name format ("@upstash/pulumi").

I am happy to create a pull request to handle any of the non-standard package names if helpful, but thought I'd raise the issue prior in case you already have plans to handle it.

Failed to register new resource (sourcemaps), no such file or directory

I'm getting this error when attempting to deploy a Next.js application:

Error: failed to register new resource SiteSourcemap5edb9939 [aws:s3/bucketObjectv2:BucketObjectv2]: 2 UNKNOWN: failed to compute asset hash for "source": failed to open asset file '.next/server/app/my-page/page.js.map': open .next/server/app/my-page/page.js.map: no such file or directory
at new Resource (/home/runner/work/my-app/my-app/.sst/platform/node_modules/@pulumi/aws/node_modules/@pulumi/resource.ts:507:13)
    at new CustomResource (/home/runner/work/my-app/my-app/.sst/platform/node_modules/@pulumi/aws/node_modules/@pulumi/resource.ts:897:9)
    at new BucketObjectv2 (/home/runner/work/my-app/my-app/.sst/platform/node_modules/@pulumi/s3/bucketObjectv2.ts:439:9)
    at file:///home/runner/work/my-app/my-app/.sst/platform/src/components/aws/nextjs.ts:1388:13
    at Array.forEach (<anonymous>)
    at file:///home/runner/work/my-app/my-app/.sst/platform/src/components/aws/nextjs.ts:1385:18
    at /home/runner/work/my-app/my-app/.sst/platform/node_modules/@pulumi/output.ts:398:31
    at Generator.next (<anonymous>)
    at /home/runner/work/my-app/my-app/.sst/platform/node_modules/@pulumi/pulumi/output.js:21:71

I traced the issue to .sst/platform/src/components/aws/nextjs.ts and its uploadSourcemaps function. I was able to patch locally by updating the source path for new aws.s3.BucketObjectv2:

function uploadSourcemaps() {
      logging.apply((logging) => {
        if (logging !== "per-route") return;

        useRoutes().apply((routes) => {
          routes.forEach(({ sourcemapPath, sourcemapKey }) => {
            if (!sourcemapPath || !sourcemapKey) return;
            outputPath.apply((outputPath) => {
              new aws.s3.BucketObjectv2(
                `${name}Sourcemap${sanitizeToPascalCase(sourcemapKey)}`,
                {
                  bucket: region.apply((region) =>
                    bootstrap.forRegion(region).then((b) => b.asset),
                  ),
                  source: new asset.FileAsset(
                    path.resolve(outputPath, sourcemapPath),
                  ),
                  key: serverFunction!.nodes.function.arn.apply((arn) =>
                    path.posix.join("sourcemaps", arn, sourcemapKey),
                  ),
                },
                { parent, retainOnDelete: true },
              );
            });
          });
        });
      });
    }

This doesn't help when attempting to deploy via CI so it'd be great if someone could look into this.

ION-220

Not possible to use an existing S3 Bucket

SST version: 0.0.194

Discord discussion: link

One of the coolest parts of SST was its ability to be used with existing infrastructure by importing existing objects, such as Buckets (e.g. https://docs.sst.dev/constructs/Bucket#importing-an-existing-bucket)

This feature seem to be missing from sst/ion completely

As a workaround, I tried to use pulumi constructs, but there are several issues:

  • aws.s3.BucketV2 gives errors, only aws.s3.Bucket works (sample below)
  • aws.s3.Bucket.onObjectCreated gives an error when used with sst commands (sample below)

Code Sample with pulumi

import * as aws from "@pulumi/aws";
import { BucketEventHandler } from "@pulumi/aws/s3";

const processor: BucketEventHandler = async (event) => {
  console.log(event);
};
async run() {
  const bucketName = process.env.S3_UPLOADS_BUCKET;
  const bucket = aws.s3.Bucket.get("Uploads", bucketName);
  bucket.onObjectCreated("Processor", processor);
}

Gives an error when applied with sst dev or sst deploy

~  Deploying

|  Error        Invalid component name "Processor". Component names must be unique.
|  Creating    Uploads aws:s3:Bucket → Processor aws:s3:BucketEventSubscription
|  Created     Uploads aws:s3:Bucket → Processor aws:s3:BucketEventSubscription

×  Failed
   Invalid component name "Processor". Component names must be unique.

This error seems straightforward, but no matter how unique/random the resource name is generated, even if the whole stack is deleted and recreated, the error is still there -- looks like an issue with pulumi when being invoked with sst

ION-238

NextJS Site - Runtime Errors with Cache bucket permissions

It looks like nothing in NextJs component never gives the lambda role permissions to write or read from the bucket

CACHE_BUCKET_NAME: bucketName,
so at runtime I'm seeing nextjs/open-next errors when its trying to read from cache like ERROR Failed to get body cache AccessDenied: Access Denied and also writing to cache ERROR { clientName: 'S3Client', commandName: 'PutObjectCommand', input: { Bu...

Deployment to CloudFlare StaticSite Fails with `Resolved credential object is not valid`

I keep getting this error with the Cloudflare provider. I set the providers.cloudflare.apiToken but had the same error.

sst dev --verbose
time=2024-03-11T13:44:44.688-04:00 level=INFO msg=plugins files="[d resource-aws-v6.10.0/ - resource-aws-v6.10.0.lock d resource-cloudflare-v5.22.0/ - resource-cloudflare-v5.22.0.lock]"
time=2024-03-11T13:44:44.692-04:00 level=INFO msg="no existing server found, starting new one"
time=2024-03-11T13:44:44.695-04:00 level=INFO msg="waiting for server to start"
SST ❍ ion 0.0.133  ready!

➜  App:        appname
   Stage:      cody

~  Deploying

(node:58827) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
|  Creating    sst:cloudflare:StaticSite → pulumi-nodejs:dynamic:Resource → WwwAssetFiles
|  Error       sst:cloudflare:StaticSite → pulumi-nodejs:dynamic:Resource → WwwAssetFiles
|  Resolved credential object is not valid
|  ADD THIS ERROR HERE https://www.notion.so/sst-dev/Flaky-errors-2a51e5e471f745ee9d0b8d69c5b4f8c8?pvs=4


❌ Failed
   sst:cloudflare:StaticSite → pulumi-nodejs:dynamic:Resource → WwwAssetFiles
   Resolved credential object is not valid
   ADD THIS ERROR HERE https://www.notion.so/sst-dev/Flaky-errors-2a51e5e471f745ee9d0b8d69c5b4f8c8?pvs=4

with this sst.config.ts :

export default $config({
  app(input) {
    return {
      name: "appname",
      removalPolicy: input?.stage === "production" ? "retain" : "remove",
      providers: {
        cloudflare: {
          accountId: "...redacted...",
        },
        aws: {
          profile: input?.stage === "production" ? "production" : "development",
        },
      },
    };
  },
  async run() {
    new sst.cloudflare.StaticSite("Www", {
      path: "packages/www",
    });
  },
});

I have the CLOUDFLARE_API_TOKEN env var set and valid AWS credentials.


Discord Link

`DatabaseName must begin with a letter and contain only alphanumeric characters.` error in Function + Posgres + Drizzle ORM setup

Simple Lambda function linked to a Postgres database giving following error when running sst dev:

❯ pnpm dev --verbose

> test-sst-ion@ dev /Users/frixaco/personal/test-sst-ion
> AWS_PROFILE=<> dev "--verbose"

time=2024-03-24T18:28:35.446+05:00 level=INFO msg="checking for bun" path="/Users/frixaco/Library/Application Support/sst/bin/bun"
time=2024-03-24T18:28:35.447+05:00 level=INFO msg=args args=[] length=0
time=2024-03-24T18:28:35.447+05:00 level=INFO msg="no existing server found, starting new one"
time=2024-03-24T18:28:35.448+05:00 level=INFO msg="waiting for server to start"
SST ❍ ion 0.0.197  ready!

➜  App:        test-sst-ion
   Stage:      frixaco
   Console:    https://console.sst.dev/local/test-sst-ion/frixaco

~  Deploying

|  Creating    TestSSTDatabase sst:aws:Postgres → TestSSTDatabaseCluster aws:rds:Cluster
|  Error       TestSSTDatabase sst:aws:Postgres → TestSSTDatabaseCluster aws:rds:Cluster
|  DatabaseName must begin with a letter and contain only alphanumeric characters.
|  94fbd721-92ae-4528-afe3-404bf911e3a6

×  Failed
   TestSSTDatabase sst:aws:Postgres → TestSSTDatabaseCluster aws:rds:Cluster
   DatabaseName must begin with a letter and contain only alphanumeric characters.
   94fbd721-92ae-4528-afe3-404bf911e3a6

sst.config.ts:

export default $config({
  app(input) {
    return {
      name: "test-sst-ion",
      removal: input?.stage === "production" ? "retain" : "remove",
      home: "aws",
    };
  },
  async run() {
    const database = new sst.aws.Postgres("TestSSTDatabase");

    new sst.aws.Function("TestSSTFunction", {
      link: [database],
      handler: "src/lambda.handler",
      url: {
        authorization: "none",
        cors: {
          allowMethods: ["GET", "POST"],
          allowOrigins: ["*"],
        },
      },
   });
  },
});

Full repro: https://github.com/frixaco/test-sst-ion

Is it a bug on Ion or did I misconfigure something?

Note: The main goal is to setup Next.js app with automatic DB migrations when using Drizzle ORM when deploying to different environments. After some digging on Discord, I found a link to an example which uses Script construct (config file). Ion doesn't have Script construct, however, Dax mentioned that it might not be needed. My idea is to create a simple Function bundled with migration files and send a POST request to that function that triggers migrate function (config file)

ION-237

Can't install `ion` in MacOS


OS: M1 v14.2.1

I tried to install ion but I got this issues

curl -fsSL https://ion.sst.dev/install | bash
grep: invalid option -- P
usage: grep [-abcdDEFGHhIiJLlMmnOopqRSsUVvwXxZz] [-A num] [-B num] [-C[num]]
	[-e pattern] [-f file] [--binary-files=value] [--color=when]
	[--context[=num]] [--directories=action] [--label] [--line-buffered]
	[--null] [pattern] [file ...]

Support `buildOutputPath` for Next.js

buildOutputPath is not supported for OpenNext in NextjsSite like it is in the CDK version of SST. I tried pointing path to where the .next output is expected, but that doesn't work b/c it expects to find Next source code it seems, or at least it checks the path before running the build command.

[ION-221] Default tags and assumeRole is not being used from app config

Hi,

Currently the following config will not set defaultTags for all created resources nor will it use the assumeRole

  app(input) {
    return {
      name: 'ion-example',
      removal: input?.stage === 'production' ? 'retain' : 'remove',
      home: 'aws',
      providers: {
        aws: {
          region: 'eu-west-1',
          profile: 'sst-dev',
          assumeRole: {
            roleArn: 'arn:aws:iam::xxxx:role/sst-deploy',
            sessionName: 'sst-deploy',
          },
          defaultTags: {
            tags: {
              Owner: 'JS',
              Project: `ion-example-${input.stage}`,
              Environment: input.stage,
              LUMIGO_TAG: input.stage,
            },
          },
        },
      },
    };
  },

Ref ProviderArgs


If you've already posted your issue on Discord, make sure to leave a link to it here.

ION-221

Cannot find package "prettier" when adding cloudflare

Maybe I'm just the only one not using prettier in my app code 🤔


sst add cloudflare
Adding provider cloudflare...
error: Cannot find package "prettier" from "$cwd/.sst/platform/src/ast/add.ts"
×  Unexpected error occurred. Please check the logs or run with --verbose for more details.
sst add cloudflare --verbose
time=2024-03-25T22:35:10.946-07:00 level=INFO msg="checking for bun" path="$path"
Adding provider cloudflare...
time=2024-03-25T22:35:10.949-07:00 level=INFO msg="esbuild building"
time=2024-03-25T22:35:10.958-07:00 level=INFO msg="esbuild built" outfile=$cwd/.sst/eval/eval-1711431310949.mjs
time=2024-03-25T22:35:10.958-07:00 level=INFO msg="evaluating config"
time=2024-03-25T22:35:11.113-07:00 level=INFO msg="config evaluated"
time=2024-03-25T22:35:11.114-07:00 level=INFO msg="checking platform"
error: Cannot find package "prettier" from "$cwd/.sst/platform/src/ast/add.ts"
time=2024-03-25T22:35:11.199-07:00 level=ERROR msg="exited with error" err="exit status 1"
×  Unexpected error occurred. Please check the logs or run with --verbose for more details.

Panic: runtime error: index out of range [0] with length 0

this happens after I use preTokenGen lambda for userPool

 const postConfirmation = new sst.aws.Function("PostConfirmation", {
      handler: "src/server/functions/post-confirm.handler",
      architecture: "arm64",
      runtime: "nodejs20.x",
      link: [DB],
    });
    const preToken = new sst.aws.Function("PreToken", {
      handler: "src/server/functions/pre-token.handler",
      architecture: "arm64",
      runtime: "nodejs20.x",
      link: [DB],
    });
    const userPool = new aws.cognito.UserPool("NubIonUserPool", {
      autoVerifiedAttributes: ["email"],
      passwordPolicy: {
        minimumLength: 8,
      },
      usernameAttributes: ["email"],
      lambdaConfig: {
        postConfirmation: postConfirmation.arn,
        preTokenGeneration: preToken.arn,
      },
    });
    const userPoolClient = new aws.cognito.UserPoolClient(
      "NubIonUserPoolClient",
      {
        userPoolId: userPool.id,
      },
    );```

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.