Skip to content
This repository was archived by the owner on May 20, 2025. It is now read-only.

Commit ff35883

Browse files
committed
update foundations content and link config
1 parent 17926ff commit ff35883

File tree

7 files changed

+431
-102
lines changed

7 files changed

+431
-102
lines changed

docs/further-reading/how-devs-use-nitric.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Projects can have as many service files as desired, and each one will map to a c
1414

1515
The Nitric SDK offers a comprehensive set of tools, including handlers for events/topics, queues, storage, key-value (KV) stores, schedules, APIs and secrets. These components are the essential building blocks for building cloud applications.
1616

17-
SDKs communicate with the Nitric Server using gRPC and Protocol Buffers, which enables the framework to support [many languages](/reference/languages). Resources defined in the SDK do not require low-level configuration, which means that application code will never contain parameters or annotations for config, such as the replication policies for data stores. This fine-grained control is handled by [Providers](/foundations/deployment/providers), which are described in the Ops workflow.
17+
SDKs communicate with the Nitric Server using gRPC and Protocol Buffers, which enables the framework to support [many languages](/reference/languages). Resources defined in the SDK do not require low-level configuration, which means that application code will never contain parameters or annotations for config, such as the replication policies for data stores. This fine-grained control is handled by [Providers](/foundations/deployment#providers), which are described in the Ops workflow.
1818

1919
## Local Cloud Emulation
2020

docs/get-started/foundations/infrastructure/index.mdx

Lines changed: 283 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@ description: Nitric allows applications to declare infrastructure requirements a
44

55
# Infrastructure
66

7-
Infrastructure from Code (IfC) is an extension of Infrastructure as Code (IaC) that takes runtime application code into consideration and enhances Separation of Concerns (SoC).
7+
If you haven't read [Why Nitric](/get-started/foundations/why-nitric) yet, you might want to start there. It explains the 'why' behind Nitric, which can help you understand the 'what' and 'how' of Nitric.
8+
9+
Nitric applies the concept of Infrastructure from Code (IfC) in a very specific way, to enhance Infrastructure as Code (IaC) and help applications with platform specific Separation of Concerns (SoC).
810

911
<Note>
10-
Several products describe themselves as "Infrastructure from Code" (IfC), but
11-
they're not all like Nitric. Many are platforms/SaaS products, not a
12-
framework. Those products have different benefits and trade-offs.
12+
"Infrastructure from Code" (IfC) is an emerging term and sometimes refers to
13+
proprietary platforms/SaaS products. Instead, Nitric is an open source
14+
application framework, that integrates with existing IaC tools, to automate
15+
the creation of infrastructure from application code.
1316
</Note>
1417

15-
Nitric's Infrastructure from Code (IfC) automates the creation of infrastructure from your application code, ensuring a clear separation between application logic and deployment concerns.
16-
17-
It abstracts the infrastructure layer, allowing developers to define what their application needs without getting bogged down in the specifics of cloud services or infrastructure configurations.
18+
Nitric separates platform-specific cloud and infrastructure interaction away from core application code, while allowing developers to define their application's requirement explicitly.
1819

1920
Sometimes it's easier to explain IfC by exploring the benefits.
2021

@@ -28,41 +29,201 @@ Nitric significantly reduces or removes cloud-specific code. For example, access
2829

2930
<TabItem label="Nitric SDK">
3031

31-
```javascript
32+
This code works equally with AWS S3, Google Cloud Storage, Azure Blob Storage, or any other storage service:
33+
34+
<CodeSwitcher tabs>
35+
36+
```javascript !!
37+
import { bucket } from '@nitric/sdk'
38+
39+
const receiptDocs = bucket('receipt-docs').allow('read')
40+
41+
export async function getReceiptDoc(filename) {
42+
return await receiptDocs.file(filename).read()
43+
}
44+
```
45+
46+
```typescript !!
3247
import { bucket } from '@nitric/sdk'
3348

34-
const profiles = bucket('profiles').allow('read')
49+
const receiptDocs = bucket('receipt-docs').allow('read')
3550

36-
export const getProfilePic = async (filename) => {
37-
return await profiles.file(filename).read()
51+
export async function getReceiptDoc(filename: string): Promise<Uint8Array> {
52+
return await receiptDocs.file(filename).read()
3853
}
3954
```
4055

56+
```python !!
57+
from nitric.resources import bucket
58+
59+
receipts_docs = bucket("receipts").allow("read")
60+
61+
async def get_receipt_doc(filename):
62+
return await receipts_docs.file(filename).read()
63+
64+
```
65+
66+
```go !!
67+
import (
68+
"context"
69+
70+
"github.com/nitrictech/go-sdk/nitric"
71+
"github.com/nitrictech/go-sdk/nitric/storage"
72+
)
73+
74+
var receiptDocs storage.BucketClient
75+
76+
func init() {
77+
receiptDocs = *nitric.NewBucket("receipt-docs").Allow(storage.BucketRead)
78+
}
79+
80+
func getReceiptDoc(ctx context.Context, filename string) ([]byte, error) {
81+
return receiptDocs.Read(ctx, filename)
82+
}
83+
```
84+
85+
```dart !!
86+
import 'package:nitric_sdk/nitric.dart';
87+
88+
final receiptDocs = Nitric.bucket("receipt-docs").allow([
89+
BucketPermission.read,
90+
]);
91+
92+
Future<List<int>> getReceiptDoc(String filename) async {
93+
return await receiptDocs.file(filename).read();
94+
}
95+
```
96+
97+
</CodeSwitcher>
98+
4199
</TabItem>
42100

43101
<TabItem label="AWS SDK">
44102

45-
```javascript
103+
This code is specific to AWS S3 and requires additional runtime setup and error handling:
104+
105+
<CodeSwitcher tabs>
106+
107+
```javascript !!
108+
import { GetObjectCommand, S3Client } from '@aws-sdk/client-s3'
109+
110+
const s3 = new S3Client({})
111+
const RECEIPT_DOCUMENTS_BUCKET = process.env.RECEIPT_DOCUMENTS_BUCKET
112+
113+
if (!RECEIPT_DOCUMENTS_BUCKET) {
114+
throw new Error('RECEIPT_DOCUMENTS_BUCKET environment variable not set')
115+
}
116+
117+
export async function getReceiptDoc(filename) {
118+
const command = new GetObjectCommand({
119+
Bucket: RECEIPT_DOCUMENTS_BUCKET,
120+
Key: filename,
121+
})
122+
123+
const response = await s3.send(command)
124+
return await response.Body.transformToByteArray()
125+
}
126+
```
127+
128+
```typescript !!
46129
import { GetObjectCommand, S3Client } from '@aws-sdk/client-s3'
47130

48-
const client = new S3Client({})
49-
const PROFILES_BUCKET = process.env.PROFILES_BUCKET
131+
const s3 = new S3Client({})
132+
const RECEIPT_DOCUMENTS_BUCKET = process.env.RECEIPT_DOCUMENTS_BUCKET
50133

51-
if (!bucket) {
52-
throw new Error('PROFILES_BUCKET environment variable not set')
134+
if (!RECEIPT_DOCUMENTS_BUCKET) {
135+
throw new Error('RECEIPT_DOCUMENTS_BUCKET environment variable not set')
53136
}
54137

55-
export const getProfilePic = async (filename) => {
138+
export async function getReceiptDoc(filename: string): Promise<Uint8Array> {
56139
const command = new GetObjectCommand({
57-
Bucket: PROFILES_BUCKET,
140+
Bucket: RECEIPT_DOCUMENTS_BUCKET,
58141
Key: filename,
59142
})
60143

61-
const response = await client.send(command)
144+
const response = await s3.send(command)
62145
return await response.Body.transformToByteArray()
63146
}
64147
```
65148

149+
```python !!
150+
import os
151+
import boto3
152+
153+
RECEIPT_DOCUMENTS_BUCKET = os.getenv('RECEIPT_DOCUMENTS_BUCKET')
154+
155+
if not RECEIPT_DOCUMENTS_BUCKET:
156+
raise EnvironmentError('RECEIPT_DOCUMENTS_BUCKET environment variable not set')
157+
158+
s3_client = boto3.client('s3')
159+
160+
def get_receipt_doc(filename):
161+
response = s3_client.get_object(Bucket=RECEIPT_DOCUMENTS_BUCKET, Key=filename)
162+
return response['Body'].read()
163+
164+
```
165+
166+
```go !!
167+
package main
168+
169+
import (
170+
"context"
171+
"os"
172+
"github.com/aws/aws-sdk-go-v2/aws"
173+
"github.com/aws/aws-sdk-go-v2/config"
174+
"github.com/aws/aws-sdk-go-v2/service/s3"
175+
"io"
176+
)
177+
178+
var receiptDocumentsBucket = os.Getenv("RECEIPT_DOCUMENTS_BUCKET")
179+
180+
func init() {
181+
if receiptDocumentsBucket == "" {
182+
panic("RECEIPT_DOCUMENTS_BUCKET environment variable not set")
183+
}
184+
}
185+
186+
func getReceiptDoc(filename string) ([]byte, error) {
187+
cfg, _ := config.LoadDefaultConfig(context.TODO())
188+
s3Client := s3.NewFromConfig(cfg)
189+
190+
resp, _ := s3Client.GetObject(context.TODO(), &s3.GetObjectInput{
191+
Bucket: aws.String(receiptDocumentsBucket),
192+
Key: aws.String(filename),
193+
})
194+
195+
defer resp.Body.Close()
196+
return io.ReadAll(resp.Body)
197+
}
198+
```
199+
200+
```dart !!
201+
import 'dart:io';
202+
import 'package:aws_s3_api/s3-2006-03-01.dart';
203+
204+
final receiptDocumentsBucket = Platform.environment['RECEIPT_DOCUMENTS_BUCKET'];
205+
206+
void checkBucketEnv() {
207+
if (receiptDocumentsBucket == null || receiptDocumentsBucket!.isEmpty) {
208+
throw Exception('RECEIPT_DOCUMENTS_BUCKET environment variable not set');
209+
}
210+
}
211+
212+
Future<List<int>> getReceiptDoc(String filename) async {
213+
checkBucketEnv();
214+
final client = S3(region: 'us-west-2'); // Adjust region
215+
final request = GetObjectRequest(
216+
bucket: receiptDocumentsBucket!,
217+
key: filename,
218+
);
219+
220+
final response = await client.getObject(request);
221+
return await response.body.toBytes();
222+
}
223+
```
224+
225+
</CodeSwitcher>
226+
66227
</TabItem>
67228

68229
</Tabs>
@@ -75,7 +236,9 @@ Nitric keeps application code independent of specific cloud services. Developers
75236

76237
For example this same code would work equally well backed by AWS SNS, AWS EventBridge, Google Cloud Pub/Sub, Azure EventGrid, Apache Kafka, or any other messaging service:
77238

78-
```javascript
239+
<CodeSwitcher tabs>
240+
241+
```javascript !!
79242
import { topic } from '@nitric/sdk'
80243

81244
const myTopic = topic('my-topic').allow('publish')
@@ -85,7 +248,59 @@ export const publishMessage = async (message) => {
85248
}
86249
```
87250

88-
We can change the underlying messaging service through a simple configuration change, without modifying the application code.
251+
```typescript !!
252+
import { topic } from '@nitric/sdk'
253+
254+
const myTopic = topic('my-topic').allow('publish')
255+
256+
export async function publishMessage(message: any) {
257+
await myTopic.publish(message)
258+
}
259+
```
260+
261+
```python !!
262+
from nitric.resources import topic
263+
264+
my_topic = topic("my-topic").allow("publish")
265+
266+
async def publish_message(message):
267+
await my_topic.publish(message)
268+
```
269+
270+
```go !!
271+
import (
272+
"context"
273+
274+
"github.com/nitrictech/go-sdk/nitric"
275+
"github.com/nitrictech/go-sdk/nitric/topics"
276+
)
277+
278+
var myTopic topics.TopicClient
279+
280+
func init() {
281+
myTopic = *nitric.NewTopic("my-topic").Allow(topics.TopicPublish)
282+
}
283+
284+
func publishMessage(ctx context.Context, message map[string]interface{}) error {
285+
return myTopic.Publish(ctx, message)
286+
}
287+
```
288+
289+
```dart !!
290+
import 'package:nitric_sdk/nitric.dart';
291+
292+
final myTopic = Nitric.topic("my-topic").allow([
293+
TopicPermission.publish,
294+
]);
295+
296+
Future<void> publishMessage(Map<String, dynamic> message) async {
297+
await myTopic.publish(message);
298+
}
299+
```
300+
301+
</CodeSwitcher>
302+
303+
We can change the underlying messaging service through a simple configuration change—which plugin to use, without modifying the application code.
89304

90305
<Tabs>
91306

@@ -136,7 +351,7 @@ provider: your_namespace/[email protected]
136351
137352
## Automate Application Infrastructure Requirements
138353
139-
Using Infrastructure as Code (IaC) tools like Terraform, Pulumi, or AWS CDK, developers can define the infrastructure requirements for their application. You can even create reusable modules for common infrastructure patterns. For example, you could create a pattern for async messaging, which includes a topic, and a subscription bound to a compute function.
354+
Using Infrastructure as Code (IaC) tools like Terraform, Pulumi, or AWS CDK, developers can define the infrastructure requirements for their application. You can even create reusable modules for common infrastructure patterns. For example, you could create a pattern for async messaging, which includes a topic, and a subscription bound to a serverless function.
140355
141356
The problem is that these tools in isolation require manual processes to keep the infrastructure in sync with the application code. Processes that are error-prone and time-consuming.
142357
@@ -150,9 +365,11 @@ If you want to see the spec for your application you can run `nitric spec`:
150365
nitric spec
151366
```
152367

368+
This spec can be automatically forwarded to plugins that generate the IaC configuration and implement a runtime API adapter the chosen services. This way, the IaC configuration is always in sync with the application code and the code always works on the target platform.
369+
153370
### No Rogue Resources or Permissions
154371

155-
Resources and access requirements are defined as close as possible to where they're used - so it's easy to see when they're no longer needed or permissions are too broad.
372+
Resources and access requirements are defined as close as possible to where they are used, making it easy to see when they are no longer needed or when permissions are too broad.
156373

157374
```javascript
158375
import { queue } from '@nitric/sdk'
@@ -174,10 +391,50 @@ The name of a resource is defined **_once_** (in the code), instead of twice (in
174391
sql('profiles')
175392
```
176393

177-
and the framework maps the requirements specification to plugins written with existing IaC tools. These tools are still responsible for provisioning the resources, roles, and permissions.
394+
Nitric maps the requirements specification to plugins written with existing IaC tools like Terraform, Pulumi or CloudFormation. These tools are still responsible for provisioning the resources, roles, and permissions, those things are never directly embedded in the application code.
178395

179396
### Don't Change App Code for Infrastructure Changes
180397

181-
You haven't imported the AWS SDK, Google Cloud SDK, or Azure SDK. You haven't written any cloud-specific code. You haven't written any mocks or tests for these cloud services, or anything that makes your code less portable.
398+
At this point you haven't imported the AWS, Google Cloud, or Azure SDK. You haven't written any cloud-specific code in your application. You haven't written any mocks or tests for these cloud services, or anything that makes your code less portable.
399+
400+
So when changes are needed for performance, cost, or compliance, you can make them instantly. Like we mentioned before, that part is just config.
401+
402+
<Tabs>
403+
404+
<TabItem label="AWS">
405+
406+
```yaml title:nitric.prod.yaml
407+
provider: nitric/[email protected]
408+
```
409+
410+
</TabItem>
411+
412+
<TabItem label="Azure">
182413
183-
So when changes are needed for performance, cost, or compliance, you can make them instantly. It's just a line of config.
414+
```yaml title:nitric.prod.yaml
415+
provider: nitric/[email protected]
416+
```
417+
418+
</TabItem>
419+
420+
<TabItem label="Google Cloud">
421+
422+
```yaml title:nitric.prod.yaml
423+
provider: nitric/[email protected]
424+
```
425+
426+
</TabItem>
427+
428+
<TabItem label="Anything Else">
429+
430+
```yaml title:nitric.prod.yaml
431+
provider: your_namespace/[email protected]
432+
```
433+
434+
</TabItem>
435+
436+
</Tabs>
437+
438+
```bash
439+
nitric up
440+
```

0 commit comments

Comments
 (0)